Удаление нежелательных свойств значений из вывода FHIR JSON в C#?

Вопрос или проблема

Я работаю над разработкой приложения .NET Core, в котором я создаю ресурсы FHIR на основе результатов из базы данных. Однако, при генерации JSON-ответа для пакета FHIR, я получаю нежелательную структуру значений в выводе. Я хочу полностью удалить эти уровни значений, чтобы JSON-ответ выглядел как стандартный ответ FHIR без вложенных полей значений.

Текущий JSON-вывод:

{
  "id": {
    "value": "bundle-example"
  },
  "type": {
    "value": "searchset"
  },
  "total": {
    "value": 5
  },
  "entry": [
    {
      "fullUrl": {
        "value": "http://example.org/fhir/Observation/8393939"
      },
      "resource": {
        "id": {
          "value": "8393939"
        },
        "status": {
          "value": "final"
        },
        "code": {
          "coding": [
            {
              "system": {
                "value": "http://loinc.org"
              },
              "code": {
                "value": "1988-5"
              },
              "display": {
                "value": "CRP"
              }
            }
          ]
        }
        // ... другие поля
      }
    }
    // ... другие записи
  ]
}

Желаемая структура JSON:

{
  "resourceType": "Bundle",
  "id": "bundle-example",
  "type": "searchset",
  "total": 5,
  "entry": [
    {
      "fullUrl": "http://example.org/fhir/Observation/8393939",
      "resource": {
        "resourceType": "Observation",
        "id": "8393939",
        "status": "final",
        "code": {
          "coding": [
            {
              "system": "http://loinc.org",
              "code": "1988-5",
              "display": "CRP"
            }
          ]
        }
        // ... другие поля
      }
    }
    // ... другие записи
  ]
}

Вот соответствующий код из моего класса ObservationService, который отвечает за генерацию пакета FHIR:

using Hl7.Fhir.Model;
using System;
using System.Data;
using System.Collections.Generic;
using FHIR.PoC.Data;

namespace FHIR.PoC.Service
{
    public class ObservationService
    {
        private readonly SpecimenRepository m_specimenRepository;

        public ObservationService(SpecimenRepository specimenRepository)
        {
            m_specimenRepository = specimenRepository;
        }

        public Bundle MapToObservations(DataTable dtDbResults, bool bIncludeSpecimen)
        {
            var bundle = new Bundle
            {
                Id = "bundle-example",
                Type = Bundle.BundleType.Searchset,
                Total = dtDbResults.Rows.Count,
                Entry = new List<Bundle.EntryComponent>()
            };

            foreach (DataRow drRow in dtDbResults.Rows)
            {
                var observation = new Observation
                {
                    Id = drRow["zissample_id"].ToString() ?? "null",
                    Status = drRow["ZISRESULTSTATUS_ID"].ToString() == "8000013" ? ObservationStatus.Final : ObservationStatus.Preliminary,
                    Code = new CodeableConcept
                    {
                        Coding = new List<Coding>
                        {
                            new Coding
                            {
                                System = "http://loinc.org",
                                Code = drRow["LOINC_CODE"] != DBNull.Value ? drRow["LOINC_CODE"].ToString() : null,
                                Display = drRow["MEASURE_CODE"] != DBNull.Value ? drRow["MEASURE_CODE"].ToString() : null
                            }
                        }
                    },
                    Subject = new ResourceReference($"Patient/{drRow["SOURCE_ID"].ToString()}"),
                    Effective = GetEffectiveDate(drRow),
                    Issued = drRow["FIRSTREPORTDATETIME"] != DBNull.Value ? (DateTimeOffset?)Convert.ToDateTime(drRow["FIRSTREPORTDATETIME"]) : null,
                    Performer = new List<ResourceReference>
                    {
                        new ResourceReference("Practitioner/VasteWaardeLabTrain")
                    },
                    Value = GetObservationValue(drRow)
                };

                ProcessReferenceRangeIfPresent(drRow, observation);

                if (bIncludeSpecimen)
                {
                    ProcessSpecimen(drRow, observation);
                }

                bundle.Entry.Add(new Bundle.EntryComponent
                {
                    FullUrl = $"http://example.org/fhir/Observation/{observation.Id}",
                    Resource = observation
                });
            }

            return bundle;
        }

В настоящее время я устанавливаю свойства ресурсов FHIR, но JSON-ответ все еще содержит структуру значений. Я также пробовал присваивать значения напрямую, не завертывая их в объект, но результат остается прежним.

Как я могу полностью удалить уровни значений из JSON-ответа, сгенерированного моими ресурсами наблюдения FHIR? Что мне следует изменить в коде, чтобы обеспечить правильную структуру ответа, как показано в желаемой структуре JSON выше?

Ответ или решение

Чтобы устранить нежелательную структуру значений в JSON-выводе FHIR в вашем приложении на .NET Core, вам необходимо изменить способ, которым вы устанавливаете свойства ресурсов FHIR в коде. Основная проблема заключается в том, что вы используете внутренние объекты value, такие как { "value": "bundle-example" }, вместо ожидаемого простого формата: "id": "bundle-example".

Анализ проблемы

Существующие ваши свойства для ресурсов и их значения используются в виде объектов со свойством value, что приводит к возникновению сложной иерархии в JSON-выводе. Например, вместо того чтобы просто задавать Id как строку, вы создаете объект вида { "value": "..." }.

Решение

Чтобы исправить это, вам нужно напрямую присваивать простые типы данных свойствам вашего объекта FHIR. Рассмотрим, как это применить на примере вашего метода MapToObservations.

Шаги по улучшению структуры JSON:

  1. Удалите структуры value: Вместо того чтобы устанавливать Observation.Id, Observation.Status и другие свойства через объект, сделайте это напрямую.

  2. Примените аналогичный подход к Bundle: При создании объекта Bundle также установите его свойства без обертки.

Обновленный код

Ниже приведен измененный код для метода MapToObservations, который устраняет ненужную структуру value:

public Bundle MapToObservations(DataTable dtDbResults, bool bIncludeSpecimen)
{
    var bundle = new Bundle
    {
        Id = "bundle-example",
        Type = Bundle.BundleType.Searchset,
        Total = dtDbResults.Rows.Count,
        Entry = new List<Bundle.EntryComponent>()
    };

    foreach (DataRow drRow in dtDbResults.Rows)
    {
        var observation = new Observation
        {
            Id = drRow["zissample_id"].ToString() ?? "null",
            Status = drRow["ZISRESULTSTATUS_ID"].ToString() == "8000013" ? ObservationStatus.Final : ObservationStatus.Preliminary,
            Code = new CodeableConcept
            {
                Coding = new List<Coding>
                {
                    new Coding
                    {
                        System = "http://loinc.org",
                        Code = drRow["LOINC_CODE"] != DBNull.Value ? drRow["LOINC_CODE"].ToString() : null,
                        Display = drRow["MEASURE_CODE"] != DBNull.Value ? drRow["MEASURE_CODE"].ToString() : null
                    }
                }
            },
            Subject = new ResourceReference($"Patient/{drRow["SOURCE_ID"].ToString()}"),
            Effective = GetEffectiveDate(drRow),
            Issued = drRow["FIRSTREPORTDATETIME"] != DBNull.Value ? (DateTimeOffset?)Convert.ToDateTime(drRow["FIRSTREPORTDATETIME"]) : null,
            Performer = new List<ResourceReference>
            {
                new ResourceReference("Practitioner/VasteWaardeLabTrain")
            },
            // Прямо устанавливаем значение без обертки
            Value = GetObservationValue(drRow)
        };

        ProcessReferenceRangeIfPresent(drRow, observation);

        if (bIncludeSpecimen)
        {
            ProcessSpecimen(drRow, observation);
        }

        bundle.Entry.Add(new Bundle.EntryComponent
        {
            FullUrl = $"http://example.org/fhir/Observation/{observation.Id}",
            Resource = observation
        });
    }

    return bundle;
}

Описание изменений

  • Упрощенное присвоение: В данном коде для свойств Id, Status, и других используются простые строки и структуры вместо обертывания в дополнительные объекты. Это и упрощает вашу структуру, и делает вывод JSON-совместимым с FHIR.

Проверка результата

После внесения этих изменений вы можете протестировать код, чтобы убедиться, что генерируемый JSON соответствует желаемому формату. Проверьте результат через FhirJsonSerializer или аналогичные инструменты в библиотеках HL7 FHIR.

Заключение

Следуя этим шагам, вы существенно улучшите выходную структуру JSON для ваших ресурсов FHIR в Dynamics Core. Снижение сложности структуры не только улучшает читаемость вашего API, но также упрощает интеграцию с другими сервисами и системами, использующими стандарт FHIR.

Оцените материал
Добавить комментарий

Капча загружается...