Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Go - Task_Output encoded REST message does not match FHIR Store model #43

Closed
shanperera opened this issue Apr 21, 2022 · 4 comments
Closed

Comments

@shanperera
Copy link

Intro

Hello, I'm using the Go package to help compose a PATCH call to our FHIR Store on GCP. I'm trying to update a Task's Output field with a reference to a QuestionnaireResponseId and I'm having trouble composing a correct PATCH call using the provided fhir/go/proto/google/fhir/proto/r4/core/resources/task_go_proto/ package. Specifically Task_Output.

Context

  • We use an in-house FHIR router client to make REST calls to the FHIR Store.
  • Our FHIR router client composes a PATCH call using the FHIR Patch Add operation, provides the path to the relevant FHIR element being patched (output), and the actual value payload to be added to the existing Task entry
  • The value payload is a []proto.Message, which in this case contains a single Task_Output entry
  • When composing the PATCH call, we first marshal each entry of the []proto.Message using a jsonformatter.AnalyticsMarshaller, afterwards we marshall the entire message into bytes using Go's json library
  • We then compose a request to the Task endpoint using the relevant payload, API parameters and headers and make the request
  • The issue I am encountering stems from a mismatch of keys, explained below

REST Call Message Mismatch

The issue I am encountering is a key mismatch between what the FHIR Store is expecting and the message generated by encoding the proto.Message.

The FHIR store expects a message like this, I have tested calls to our FHIR Store with the message format below using Postman and a 200 Success message is returned and the entries are updated (Given a proper FHIR QuestionnaireResponseId is passed rather than Q...1234...):

[
      {
        "op": "add",
        "path": "/output",
        "value": [
            {
                "type": {
                    "text": "QuestionnaireResponse generated"
                },
                "valueReference": {
                    "reference":  "QuestionnaireResponse/QuestionnaireResponseId_12345678"
                }
            }
        ]
    }
]

The message generated by our backend is like this, notice the value key and the two reference entries, testing these calls to our FHIR Store using Postman returns a 400 Bad Request error:

[
    {
        "op": "add",
        "path": "/output",
        "value": [
            {
                "type": {
                    "text": "QuestionnaireResponse generated"
                },
                "value": {
                    "reference": {
                        "reference": "QuestionnaireResponse/QuestionnaireResponse/questionnaireId"
                    }
                }
            }
        ]
    }
]

Issue

Essentially, the FHIR Store is expecting the key valueReference but the message generated by our backend using the Task_Output model found in fhir/go/proto/google/fhir/proto/r4/core/resources/task_go_proto/task.pb.go is returning the key as value. I believe this is because the proto and json names are set to value in the provided library. The valueReference field aligns with the following Task Output example.

For more context, here is the structure of the Task_Output value payload that is being used in the PATCH call:

/**
questionnaireId is the FHIR ID for the questionnaireResponseId we are trying to PATCH to the Task Output entry
QuestionnaireResponseGenerated = "QuestionnaireResponse generated"
QuestionnaireResponseResourceType = "QuestionnaireResponse" 
**/
&task_go_proto.Task_Output{
    Type: &datatypes_go_proto.CodeableConcept{
        Text: &datatypes_go_proto.String{
            Value: fhir_constants.QuestionnaireResponseGenerated, 
         },
     },
     Value: &task_go_proto.Task_Output_ValueX{
         Choice: &task_go_proto.Task_Output_ValueX_Reference{
             Reference: &datatypes_go_proto.Reference{
                 Reference: &datatypes_go_proto.Reference_QuestionnaireResponseId{
                     QuestionnaireResponseId: &datatypes_go_proto.ReferenceId{
                         Value: fmt.Sprintf("%s/%s", fhir_constants.QuestionnaireResponseResourceType, questionnaireId),
                     },
                  },
               },
           },
       },
},

I've tried multiple variations of the Task_Output_ValueX field but they all return the value key. I've tried extending the Task_Output class as well using a struct of my own but the fields outside Task_Output get ignored by the jsonformatter.Marshaller

Any insight into possible solutions for this problem would be greatly appreciated. Any more information or context that you may need, I will be happy to provide. Thank you!

@nikklassen
Copy link
Member

I see that you're using the NewAnalyticsMarshaller. This constructor is used specifically for generating a JSON object that conforms to the SQL on FHIR proposal https://github.com/FHIR/sql-on-fhir/blob/master/sql-on-fhir.md. It seems our godocs could be improved here.

To generate FHIR conformant JSON you'll want to use the default NewMarshaller.

output := &task_go_proto.Task_Output{
  Type: &datatypes_go_proto.CodeableConcept{
    Text: &datatypes_go_proto.String{
      Value: "generated",
    },
  },
  Value: &task_go_proto.Task_Output_ValueX{
    Choice: &task_go_proto.Task_Output_ValueX_Reference{
      Reference: &datatypes_go_proto.Reference{
        Reference: &datatypes_go_proto.Reference_QuestionnaireResponseId{
          QuestionnaireResponseId: &datatypes_go_proto.ReferenceId{
            Value: "1",
          },
        },
      },
    },
  },
}

m, err := jsonformat.NewMarshaller(true, "", "  ", fhirversion.R4)
if err != nil {
  panic(err)
}
data, err := m.MarshalElement(output)
if err != nil {
  panic(err)
}
fmt.Printf("output: %s", data)

prints

{
  "type": {
    "text": "generated"
  },
  "valueReference": {
    "reference": "QuestionnaireResponse/1"
  }
}

@shanperera
Copy link
Author

shanperera commented Apr 22, 2022

Hey @nikklassen, thank you, that solved the issue with the marshalling!
However, the output contains a new entry resourceType which is not accepted in FHIR PATCH calls. Is there a way to workaround this? This was our reasoning for using the AnalyticsMarshaller but since you mentioned its for SQL we will have to make this change on our end.

output: {
  "resourceType": "Output",
  "type": {
    "text": "generated"
  },
  "valueReference": {
    "reference": "QuestionnaireResponse/1"
  }

@nikklassen
Copy link
Member

Did you use the MarshalElement function? As you can see in my sample output, this function does not output the resourceType field.

@shanperera
Copy link
Author

It looks like our version of the library has to be updated because we can't see a reference to MarshalElement. Thanks for the help @nikklassen, I'll close this issue now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants