fhir: Cannot convert nested resource from protobuf to JSON

There are likely other places where this would also be the case, but I found it when using resource in Parameters.Parameter. Trying to pass a resource (e.g. Parameters) into resource throws an error, and if you do it directly mypy will give you an error as well. From what I can tell the proper way is to pack it into an Any protobuf, but then when printing to JSON it prints invalid JSON.

Here’s some sample code that reproduces the issue:

from google.fhir.r4 import json_format
from proto.google.fhir.proto.r4.core.resources.bundle_and_contained_resource_pb2 import (  # noqa: E501
    Bundle,
    ContainedResource,
)
from google.protobuf.any_pb2 import Any as AnyPB
from proto.google.fhir.proto.r4.core.resources.parameters_pb2 import Parameters
from proto.google.fhir.proto.r4.core.datatypes_pb2 import Uri

from uuid import uuid4

raw_nested_resource = Parameters()

packed_nested_resource = AnyPB()
packed_nested_resource.Pack(raw_nested_resource)


def convert_nested_resource_to_json(nested_resource) -> None:
    entry = Bundle.Entry(
        full_url=Uri(value=f"urn:uuid:{uuid4()}"),
        resource=ContainedResource(
            parameters=Parameters(
                parameter=[Parameters.Parameter(resource=nested_resource)]
            )
        ),
    )

    print(json_format.pretty_print_fhir_to_json_string(entry))


print("Converting packed nested resource to json:")
convert_nested_resource_to_json(packed_nested_resource)

print("\nConverting raw nested resource to json:")
convert_nested_resource_to_json(raw_nested_resource)

and the output:

$ python3 test_fhir.py
Converting packed nested resource to json:
{
  "fullUrl": "urn:uuid:eca063c6-48da-4619-9ae6-89bde23b689a",
  "resource": {
    "resourceType": "Parameters",
    "parameter": [
      {
        "resource":
      }
    ]
  }
}

Converting raw nested resource to json:
Traceback (most recent call last):
  File "test_fhir.py", line 35, in <module>
    convert_nested_resource_to_json(raw_nested_resource)
  File "test_fhir.py", line 23, in convert_nested_resource_to_json
    parameter=[Parameters.Parameter(resource=nested_resource)]
TypeError: Parameter to MergeFrom() must be instance of same class: expected google.protobuf.Any got google.fhir.r4.core.Parameters.

If you take out the variable and hardcode nested_resource to Parameters(), mypy will also give you an error:

Argument “resource” to “Parameter” has incompatible type “Parameters”; expected “Optional[google.protobuf.any_pb2.Any]”

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 15

Commits related to this issue

Most upvoted comments

RE: If you give it an Any it doesn’t know how to convert to a contained resource and just ends up being empty

This is actually working as intended. The usage of Any here is not to allow an arbitrary resource, there’s still only ONE correct proto type to use here, ContainedResource. The only reason we type it as Any rather than ContainedResource is to avoid the dependency loop I described above. If we allow that interdependency via ContainedResource, it took like 15 minutes to build the resources 😦

FYI the fix to this change has now been pushed to HEAD - we’ll cut a release this afternoon that contains this bugfix.

Awesome, great find and great fix. Unfortunately we’re not really set up to accept PRs quite yet, so we’ll handle on our end, but I really appreciate you digging in and making our job easier 😃