fhir-sdk
fhir-sdk copied to clipboard
Duplicate `resourceType` entry when serializing `Resource` enum to json
fhir_model::r4b::reources::generated::Resource enum has a duplicate resourceType field when serialized to json.
Given the following exampe:
#[test]
fn test_serialization() {
let subscription_status = SubscriptionStatus::builder()
.r#type(SubscriptionNotificationType::EventNotification)
.subscription(Reference::builder().build().unwrap())
.build()
.unwrap();
println!("SubscriptionStatus: {}", serde_json::ser::to_string(&subscription_status).unwrap());
let resource = Resource::SubscriptionStatus(subscription_status);
println!("Resource: {}", serde_json::ser::to_string(&resource).unwrap());
}
The SubscriptionStatus is serialized to
{"resourceType":"SubscriptionStatus","type":"event-notification","subscription":{}}
When wrapped in Resource::SubscriptionStatus, it is serialized to
{"resourceType":"SubscriptionStatus","resourceType":"SubscriptionStatus","type":"event-notification","subscription":{}}
Notice the duplicate resourceType in the json.
It seems to be caused by this serde tag at fhir-model/src/r4b/resources/generated.rs:114923
#[serde(tag = "resourceType")]
When changed to this, it serializes correctly.
#[serde(untagged)]
And the result:
{"resourceType":"SubscriptionStatus","type":"event-notification","subscription":{}}
Hmm unfortunately, when making the enum untagged, it cannot deserialize properly anymore (tests fail). Maybe it seems like a serde issue that it produces the field twice? I am unsure how to avoid it at least. The enum seems to be needed as tagged..
Hi @FlixCoder,
I’m interested in helping investigate and potentially fix the duplicate resourceType serialization issue described here. Before I start, I wanted to check if you or anyone else is already working on this, or if you’d be open to a PR if I find a viable solution.
My plan is to:
- Review the enum and struct serde annotations involved,
- Experiment with serde attributes and/or custom serialization to avoid the duplication while preserving deserialization,
- Share any findings or workarounds I discover.
Please let me know if you have any guidance or if it’s okay for me to proceed.
Thank you!
Hi, at first: thank you!
I have investigated this before:
- The generic
Resourceenum is using the tagresourceTypeto distinguish different resource types, as per spec. - The specific resource types also have a resource type field, because serialization needs to produce the
resourceTypeas per spec. Deserialization should also technically fail if it is the wrong resource type, but not sure if I even made sure of that. - Now I simply used the specific resources in the generic resource, which means the tag is produced twice during serialization, but deserialization works on a single value obvisouly.
I am not working on this and would welcome a PR if it is a sensible solution. I imagine this is just a nuisance and not any real issue, so I wasn't invested to put significant effort into it.
If you fix this, make sure you fix it in the code generator and not the generated files, though :D
A few thoughts on a fix:
- If serde allowed to only use the enum tag for deserialization, that would probably be the easiest fix
- Manual serde implementations would be a huge change in size and effort and would not make sense in terms of this issue. However, it might make sense in terms of compile time (compare it to fhirbolt, it has custom serde). And after this happened, this issue would probably also be easy to fix, if it isn't fixed already then.
- Might make sense to make sure of the correct resource type during deserialization of specific resources ^^