HL7 FHIR序列化到asp.net web api中的json

pet*_*low 5 asp.net-web-api hl7-fhir datacontractjsonserializer

我正在使用由Ewout Kramer创建的HL7.Fhir nuget package 0.9.3.

我正在使用ASP.NET Web API,但不幸的是,内置的JSON序列化不能正确生成JSON.它包含很多这样的:

"<IdentifierElement>k__BackingField"
Run Code Online (Sandbox Code Playgroud)

正如框架所示,此代码有效......

public HttpResponseMessage GetConformance()
    {
        var conformance = new Conformance();
        var json = FhirSerializer.SerializeResourceToJson(conformance);
        return new HttpResponseMessage{Content = new StringContent(json)};
    }
Run Code Online (Sandbox Code Playgroud)

但这将变得非常重复,并且不遵循Web API的"按惯例"json/xml序列化方法.

是否有其他FHIR对象包可用,或者我应该自己编写?

Ewo*_*mer 9

虽然较新版本的HL7.Fhir NuGet包(目前处于测试阶段)将携带额外的[DataContract]和[DataMember]属性,从而防止出现这类错误,但标准.NET DataContract序列化程序将无法序列化 - 内存POCO是正确的FHIR XML和Json表示.FHIR序列化具有关于如何使用XML和json的特定规则,即使不是不可能,也很难使用DataContract序列化器的(有限的)可能性进行配置.

但是,也没有必要为您在codesnippet中显示的每个调用调用FhirSerializer(事实上,这将是一个WebApi反模式).例如,我们的FHIR服务器(位于http://spark.furore.com/fhir)基于WebApi,并使用自定义MediaTypeFormatter来处理此问题.为了了解它的外观,我们创建了两个格式化程序,一个用于json,另一个用于xml:

public class JsonFhirFormatter : MediaTypeFormatter
{
        public JsonFhirFormatter() : base()
        {
            foreach (var mediaType in ContentType.JSON_CONTENT_HEADERS)
                SupportedMediaTypes.Add(new MediaTypeHeaderValue(mediaType));
        }
}
Run Code Online (Sandbox Code Playgroud)

这告诉框架这个格式化程序将采用ContentType.JSON_CONTENT_HEADERS中的任何格式(它们是application/json和一些常见的变体),并且能够解析和读取FHIR ModelTypes:

public override bool CanReadType(Type type)
{
    return type == typeof(ResourceEntry) || type == typeof(Bundle) || (type == typeof(TagList));
}

public override bool CanWriteType(Type type)
{
    return type == typeof(ResourceEntry) || type == typeof(Bundle) || (type == typeof(TagList)) || type == typeof(OperationOutcome);
}
Run Code Online (Sandbox Code Playgroud)

最后,您必须覆盖ReadFromStreamAsync和WriteToStreamAsync方法:

public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
    // Some code left out...
    XmlWriter writer = new XmlTextWriter(writeStream, Encoding.UTF8);

    if (type == typeof(ResourceEntry))
    {
        ResourceEntry entry = (ResourceEntry)value;
        FhirSerializer.SerializeResource(entry.Resource, writer);

        content.Headers.SetFhirTags(entry.Tags);
    }
Run Code Online (Sandbox Code Playgroud)

现在,一旦你完成了,你的控制器就可以做到:

[HttpGet, Route("metadata")]
public ResourceEntry Metadata()
{
   return service.Conformance();
}

[HttpOptions, Route("")]
public ResourceEntry Options()
{
   return service.Conformance();
}
Run Code Online (Sandbox Code Playgroud)

请注意,我们的服务器不使用Resources作为参数并在控制器中返回值.资源不允许您捕获重要的元数据(如id,version-id,最后修改日期等).通过在我的控制器中使用ResourceEntry,可以使用资源数据传递此数据,并且WebApi框架可以将此元数据绑定到适当的HTTP标头.