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
- Fixes bug in C++ parser where empty contained resources would print with incorrect trailing comma. See #25 PiperOrigin-RevId: 380668911 — committed to google/fhir by nickgeorge 3 years ago
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
Anyhere 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 asAnyrather thanContainedResourceis 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 😃