Условная десериализация словаря или списка объектов - PullRequest
0 голосов
/ 23 ноября 2018

Я отправляю GET-запрос в Rest API, который возвращает JSON в двух разных форматах (основываясь на некоторых внешних настройках, на которые я не могу повлиять).Я могу получить:

"content": {
    "fields": [
     {
         "name": "test1",
         "value": 1
     },
     {
         "name": "test2",
         "value": "test"
     },
     {
         "name": "test3",
         "value": "test",
         "links": [...]
     }
   ]
}

или

"content": {
  "test1": 1,
  "test2": "test",
  "test3": "test"
}

Вы можете видеть, что я получаю список объектов, содержащих свойства name и value (наряду с некоторыми другими свойствамикак links), или я получаю один объект, содержащий пары ключ-значение, как в словаре.Теперь я хочу узнать, существует ли способ условно десериализовать JSON в класс с Dictionary<string, string> и List<Field> свойствами, подобными этому:

[Serializable]
public class Content
{
    /// <summary>
    /// The Type of the Content
    /// </summary>
    public string _Type { get; set; }

    public Dictionary<string, string> Dictionary { get; set; }

    public List<Field> Fields { get; set; }
}

и заполнить словарь или список полей в зависимости отна JSON.

1 Ответ

0 голосов
/ 25 ноября 2018

Вы можете справиться с этой ситуацией, создав пользовательский JsonConverter для вашего Content класса, как показано ниже.Он работает путем загрузки части JSON content в JObject и проверки наличия свойства fields, чтобы определить, как заполнить экземпляр Content.

public class ContentConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Content);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        Content content = new Content();
        if (jo["fields"] != null)
        {
            // if the fields property is present, we have a list of fields
            content.Fields = jo["fields"].ToObject<List<Field>>(serializer);
            content._Type = "Fields";
        }
        else
        {
            // fields property is not present so we have a simple dictionary
            content.Dictionary = jo.Properties().ToDictionary(p => p.Name, p => (string)p.Value);
            content._Type = "Dictionary";
        }
        return content;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Я не был уверен, как вы хотите обработать свойство _Type, поэтому я просто установил для него значение «Поля» или «Словарь», чтобы указать, какое свойство было заполнено.Не стесняйтесь изменять его в соответствии с вашими потребностями.

Чтобы использовать конвертер, просто добавьте атрибут [JsonConverter] в свой класс Content следующим образом:

[JsonConverter(typeof(ContentConverter))]
public class Content
{
    ...
}

Вот рабочийдемо: https://dotnetfiddle.net/geg5fA

...