ссылки json не сохраняются при десериализации данных - PullRequest
1 голос
/ 24 мая 2019

Я пытаюсь загрузить данные JSON в свою базу данных. Данные хорошо структурированы и могут повторяться по всей структуре. Для повторяющихся элементов я хотел бы использовать идентификаторы и ссылки, поэтому мне не нужно дублировать код.

В настоящее время я использую json.NET для десериализации и не могу получить ссылки для правильной десериализации. Я постоянно получаю нулевые значения для элементов, которые пытаюсь заполнить ссылками.

Я попытался структурировать ссылки множеством способов, используя как идентификаторы, так и синтаксис URI. Я получил тот же результат, независимо от того, как я структурирую ссылки.

Вот код C #, который я использую для десериализации:

String dir = Directory.GetCurrentDirectory() + "\\wwwroot\\json\\";
String incidentJson = System.IO.File.ReadAllText(dir + "incident_test.json");
IncidentArray incidents = JsonConvert.DeserializeObject<IncidentArray>(
    incidentJson
    ,new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.All }
);

Вот класс, к которому я пытаюсь десериализовать данные:

public class IncidentArray
{
    public Incident[] Incidents { get; set; }
}

public class Incident
{
    public Jurisdiction Jurisdiction { get; set; }
}

public class Jurisdiction
{
    public String Code { get; set; }
    public String Name { get; set; }
    public String Description { get; set; }
}

Вот инцидент_test.json, который отлично разбирается:

{
  "incidents": [
    {
        "jurisdiction": {
          "code": "CD",
          "name": "City Division",
          "description": "City Division, Portland OR USA"
        }
    }
  ]
}

А вот инцидент_test.json со ссылками. В десериализованном объекте юрисдикция не указана:

{
  "incidents": [
    {
      "jurisdiction": { "$ref": "1" }
    }
  ],
  "definitions": {
    "jurisdiction": {
      "$id": "1",
      "code": "CD",
      "name": "City Division",
      "description": "City Division, Portland OR USA"
    }
  }
}

Я ожидаю, что объект, полученный в результате десериализации, будет заполнен данными в ссылочных данных json. Как уже говорилось, вместо этого я получаю нулевое значение.

РАЗРЕШЕНО : desmondgc определенно указал мне правильное направление своим ответом ниже, но это немного больше, чем порядок объектов. Я провел еще несколько тестов с учетом порядка и размещения объектов. Это десериализует и захватывает ссылку:

{
    "incidents": [
    {
      "jurisdiction": {
              "$id": "1",
          "code": "CD",
          "name": "City Division",
          "description": "City Division, Portland OR USA"
      }
    },
    {
      "jurisdiction": { "$ref": "1" }
    }
    ]
}

и если я создам десериализатор следующим образом:

IncidentArray incidents = JsonConvert.DeserializeObject<IncidentArray(
    incidentJson
    ,new JsonSerializerSettings {
        PreserveReferencesHandling = PreserveReferencesHandling.All
        ,MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead
    }
);

Это тоже работает:

{
    "incidents": [
    {
      "jurisdiction": {
          "code": "CD",
          "name": "City Division",
              "$id": "1",
          "description": "City Division, Portland OR USA"
      }
    },
    {
      "jurisdiction": { "$ref": "1" }
    }
    ]
}

из-за свойства MetadataPropertyHandling.

Очевидно, здесь важен порядок, и в моих исходных данных испытаний порядок был неправильным. Однако другим важным фактором, по-видимому, является тот факт, что в моем первоначальном тесте json объект с идентификатором ссылки фактически не десериализовался, потому что он не соответствовал структуре объекта, к которому я десериализовался. В результате не было объекта, который можно было бы скопировать в эталонный объект, когда десериализатор пытался его обработать.

Так важен порядок, но важна и структура объекта. Свойство id должно помечать объект, который будет обрабатывать десериализатор, а эталонный объект должен находиться в том месте на графе объектов, где десериализатор распознает его как тот же тип, что и исходный объект.

1 Ответ

0 голосов
/ 25 мая 2019

Вероятно, это проблема из-за появления $ ref перед $ id, как описано в документации Json.NET:

Свойства метаданных, такие как $ id, должны находиться в начале объекта JSON.быть успешно обнаруженным во время десериализации.Если вы не можете контролировать порядок свойств в вашем объекте JSON, то MetadataPropertyHandling можно использовать для снятия этого ограничения.

https://www.newtonsoft.com/json/help/html/PreserveObjectReferences.htm

...