No value in FHIR extensions - hl7-fhir

I have a C# REST API that uses the Hl7.Fhir.R4 library (3.7.0) with a POST method that receives an object of type Hl7.Fhir.Model.Patient:
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[HttpPost()]
public async Task<IActionResult> Post(Patient patient)
{
IActionResult status = NotFound();
...
}
The Patient object has a list of extensions:
"extension": [
{
"url": "http://example.com/fhir/extension/patient/origin",
"valueString": "test"
},
{
"url": "http://example.com/fhir/extension/patient/domainId",
"valueInt" : "10"
}...
When receiving the JSON as a parameter in the POST function, all the fields have a better value than those of type 'Hl7.Fhir.Model.DataType':
Extension[0]
Children: {Hl7.Fhir.Model.Extension.<get_Children>d__17}
ElementId: null
NamedChildren: {Hl7.Fhir.Model.Extension.<get_NamedChildren>d__19}
Extension: Count = 0
TypeName: "Extension"
Url: "http://example.com/fhir/extension/patient/origin"
Value: null
Am I missing some decorator or attribute or simply can't the object be directly deserialized?

Did you use the FhirJsonParser from the library to parse the data? You cannot use a regular JSON parser, because it will not be able to handle the FHIR model correctly.
ETA:
As you now mention in your question, the object cannot be directly deserialized, see first part of my response.
Maybe you can take a look at this project to see how it's done there: https://github.com/brianpos/fhir-net-web-api

Related

How do you get the property value from a FHIR property using FhirClient

I am using the following code to call the NHS Retrieve Reference Data method
var result = await fhirClient.ReadAsync<CodeSystem>(url);
which returns the following Json (this is a snippet of the full json)
concept": [
{
"code": "BOOKED_CLINICAL_NEED",
"display": "Booked more urgently due to clinical need",
"property": [
{
"code": "effectiveFrom",
"valueDateTime": "2019-07-23T17:09:56.000Z"
},
{
"code": "commentIsMandatory",
"valueBoolean": true
},
{
"code": "canCancelAppointment",
"valueBoolean": false
}
]
}
I have used the GetExtensionValue method for other calls when the data is within an extension but I can't find a similar method for properties.
Is there a simple method or do I need to just cast into the required type manually?
Thanks in advance
There is no convenience method for this. However, the properties per concept are a list, so you could for example iterate over the concepts and select the properties with boolean values using regular list methods:
foreach (var c in myCodeSystem.Concept)
{
var booleanProperties = c.Property.Where(p => (p.Value.TypeName == "boolean"));
// do something with these properties
}
or find all concepts that have a boolean property:
var conceptsWithDateTimeProperties = myCodeSystem.Concept.Where(c => c.Property.Exists(p => (p.Value.TypeName == "dateTime")));
Of course you can make your selections as specific as you need.

What is the most elegant way in Golang to create JSON-RPC struct with params

I'm creating a Golang app to communicate with proprietary third-party JSON-RPC API that is sensitive to the order of elements.
Request should be sent using POST over HTTPS. Here is a request sample:
{
"jsonrpc": "2.0",
"method": "ab_123",
"params": [
"ee0fe150-6648-11ed-bd23-c1392b9c96ae",
"test#example.com",
"NONE"
]
}
In API docs it's documented that first param should be id, second param is email and third param is name. There are may be dozens of params, some of them are optional (can have value NONE).
I'm looking for the most elegant way to create the request struct that will be readable and easy maintainable.
Here is what I have so far:
type APIRequest struct {
Jsonrpc string `json:"jsonrpc"`
Method string `json:"method"`
Params []string `json:"params"`
}
var request = APIRequest{
Jsonrpc: "2.0",
Method: "ab_123",
Params: []string{
"ee0fe150-6648-11ed-bd23-c1392b9c96ae",
"test#example.com",
"NONE",
},
}

/* in transcoding from HTTP to gRPC

rpc CreateBook(CreateBookRequest) returns (Book) {
option (google.api.http) = {
post: "/v1/{parent=publishers/*}/books"
body: "book"
};
}
message CreateBookRequest {
// The publisher who will publish this book.
// When using HTTP/JSON, this field is automatically populated based
// on the URI, because of the `{parent=publishers/*}` syntax.
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {
child_type: "library.googleapis.com/Book"
}];
Book book = 2 [(google.api.field_behavior) = REQUIRED];
string book_id = 3;
}
I don't understand post: "/v1/{parent=publishers/*}/books"
I thought publishers was a field in CreateBookRequest, then it populates to http, so it is something like this
post: "/v1/parent=publishers_field_value/books"
But publishers is not a field in CreateBookRequest
No, publishers is part of the expected value of the parent field. So suppose you have a protobuf request like this:
{
"parent": "publishers/pub1",
"book_id": "xyz"
"book": {
"author": "Stacy"
}
}
That can be transcoded by a client into an HTTP request with:
Method: POST
URI: /v1/publishers/pub1/books?bookId=xyz (with the appropriate host name)
Body:
{
"author": "Stacy"
}
If you try to specify a request with a parent that doesn't match publishers/*, I'd expect transcoding to fail.
That's in terms of transcoding from protobuf to HTTP, in the request. (That's the direction I'm most familiar with, having been coding it in C# just this week...)
In the server, it should just be the opposite - so given the HTTP request above, the server should come up with the original protobuf request including parent="publishers/pub1".
For a lot more information on all of this, see the proto defining HttpRule.

Updating meta fields in Shopify with GrapQL

I've never used GraphQL before so I am really lacking knowledge on how to go about this. I'm wanting to update product meta fields on Shopify and it appears this is the only way. What I've done so far is really fumbling...
My JSON is:
{
"input": {
"id": "gid://shopify/Product/749521178847",
"metafields": [
{
"id": "gid://shopify/Metafield/2223333",
"value": "Training Grounds"
}
]
}
}
I've minified this to:
{"input":{"id":"gid://shopify/Product/749521178847","metafields":[{"id":"gid://shopify/Metafield/2223333","value":"The Training Grounds"}]}}
And am then using an HTTP request to:
https://MYSTORE.myshopify.com/api/2021-10/graphql.json?query={"input":{"id":"gid://shopify/Product/749521178847","metafields":[{"id":"gid://shopify/Metafield/2223333","value":"The Training Grounds"}]}}
I get the error:
SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data
I don't know if any of this is correct. If it is, I don't know if ?query= is the right variable to pass it through on.
I recommend you start using Postman, thunder client, or similar to write your graphql queries first, you will learn a lot about how graphql works and the error msgs will be a lot more useful.
To easily connect with Shopify on this stage, go to a store and create a private app, now you can use this for authenticating your API calls.
After that the Shopify graphql works on POST, you can't write your request on GET mode.
It needs to be a POST and you are missing type of operation mutation in this case and what it is.
Postman has https://www.postman.com/lively-moon-541169/workspace/purego-apis/example/16545848-bf0d1589-09b1-4ec6-ba63-a65a56b500eb examples of how to do the calls which can help you.
Also you can check GraphiQL app on shopify to test all the queries before making the programmatic queries
Updating an existing metafield:
mutation {
metafieldsSet(metafields: [
{namespace: "YOURNAMESPACE", ownerId: "gid://shopify/Customer/CUSTOMER_ID", type: "single_line_text_field", key: "YOURKEY", value: "THIS IS NEW VALUE"}
]) {
metafields {
key
value
}
userErrors {
field
message
}
}
}
Creating new metafield:
mutation {
customerUpdate(input: {
id: "gid://shopify/Customer/CUSTOMER_ID",
metafields: [
{key: "newkey", value: "some value", type: "single_line_text_field", namespace: "some namespace"},
]
}) {
userErrors {
field
message
}
}
}

Is there a way to get a structure of a Strapi CMS Content Type?

A content-type "Product" having the following fields:
string title
int qty
string description
double price
Is there an API endpoint to retrieve the structure or schema of the "Product" content-type as opposed to getting the values?
For example: On endpoint localhost:1337/products, and response can be like:
[
{
field: "title",
type: "string",
other: "col-xs-12, col-5"
},
{
field: "qty",
type: "int"
},
{
field: "description",
type: "string"
},
{
field: "price",
type: "double"
}
]
where the structure of the schema or the table is sent instead of the actual values?
If not in Strapi CMS, is this possible on other headless CMS such as Hasura and Sanity?
You need to use Models, from the link:
Link is dead -> New link
Models are a representation of the database's structure. They are split into two separate files. A JavaScript file that contains the model options (e.g: lifecycle hooks), and a JSON file that represents the data structure stored in the database.
This is exactly what you are after.
The way I GET this info is by adding a custom endpoint - check my answers here for how to do this - https://stackoverflow.com/a/63283807/5064324 & https://stackoverflow.com/a/62634233/5064324.
For handlers you can do something like:
async getProductModel(ctx) {
return strapi.models['product'].allAttributes;
}
I needed the solution for all Content Types so I made a plugin with /modelStructure/* endpoints where you can supply the model name and then pass to a handler:
//more generic wrapper
async getModel(ctx) {
const { model } = ctx.params;
let data = strapi.models[model].allAttributes;
return data;
},
async getProductModel(ctx) {
ctx.params['model'] = "product"
return this.getModel(ctx)
},
//define all endpoints you need, like maybe a Page content type
async getPageModel(ctx) {
ctx.params['model'] = "page"
return this.getModel(ctx)
},
//finally I ended up writing a `allModels` handler
async getAllModels(ctx) {
Object.keys(strapi.models).forEach(key => {
//iterate through all models
//possibly filter some models
//iterate through all fields
Object.keys(strapi.models[key].allAttributes).forEach(fieldKey => {
//build the response - iterate through models and all their fields
}
}
//return your desired custom response
}
Comments & questions welcome
This answer pointed me in the right direction, but strapi.models was undefined for me on strapi 4.4.3.
What worked for me was a controller like so:
async getFields(ctx) {
const model = strapi.db.config.models.find( model => model.collectionName === 'clients' );
return model.attributes;
},
Where clients is replaced by the plural name of your content-type.

Resources