Сериализация HL7 FHIR в json в веб-API asp.net

Я использую пакет HL7.Fhir nuget 0.9.3, созданный Эвоутом Крамером.

Я связываю это с веб-API ASP.NET, но, к сожалению, встроенная сериализация JSON неправильно генерирует JSON. В нем много всего:

"<IdentifierElement>k__BackingField"

Как было предложено фреймворком, этот код работает...

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

но это станет довольно повторяющимся и не соответствует методам сериализации json/xml "по соглашению" веб-API.

Существуют ли какие-либо другие доступные пакеты объектов FHIR или я должен просто написать свой собственный?


person peter.swallow    schedule 14.01.2014    source источник


Ответы (1)


Хотя более новая версия пакета HL7.Fhir NuGet (в настоящее время находится в стадии бета-тестирования) будет содержать дополнительные атрибуты [DataContract] и [DataMember] и, таким образом, предотвратит подобные ошибки, стандартный сериализатор .NET DataContract не сможет сериализовать памяти POCO в правильное представление FHIR XML и Json. Сериализация FHIR имеет определенные правила использования как XML, так и json, которые трудно, если вообще возможно, настроить с использованием (ограниченных) возможностей сериализатора DataContract.

Однако также нет необходимости вызывать 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));
        }
}

Это сообщает фреймворку, что форматтер примет любой из форматов в ContentType.JSON_CONTENT_HEADERS (которые представляют собой application/json и некоторые распространенные варианты) и сможет анализировать и читать типы моделей FHIR:

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);
}

Наконец, вы должны переопределить методы 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);
    }

Теперь, когда вы это сделали, ваш контроллер может просто сделать:

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

[HttpOptions, Route("")]
public ResourceEntry Options()
{
   return service.Conformance();
}

Обратите внимание, что наш сервер не использует ресурсы в качестве параметров и возвращаемых значений в контроллере. Ресурсы не позволят вам получить важные метаданные (например, идентификатор, идентификатор версии, дату последнего изменения и т. д.). Используя ResourceEntry в моем контроллере, эти данные можно передавать вместе с данными ресурсов, а платформа WebApi может связать эти метаданные с соответствующими заголовками HTTP.

person Ewout Kramer    schedule 15.01.2014
comment
Спасибо, Эвут. Я все еще использую стабильные пакеты nuget 0.9.3, поэтому упускаю несколько вещей, но это действительно полезно. Вы разместили фрагмент XML в 3-м блоке кода вместо JSON, но я понял. Спасибо :) - person peter.swallow; 15.01.2014
comment
@Ewout, вы можете добавить атрибут [HttpOptions ...] в метод метаданных. Вам не нужно добавлять дополнительные методы. - person Richard Schneider; 16.01.2014
comment
@Ewout Вы создали собственный класс JsonFhirFormatter. Но как привязать этот форматер к методу контроллера (т.е. Метаданные()). - person Yang You; 02.02.2017