Десериализовать JSON массив объектов с одним атрибутом в коллекцию строк - PullRequest
1 голос
/ 19 марта 2020

Я все еще изучаю Newtonsoft. Json, и мне было интересно, есть ли хороший способ десериализации массива JSON ( ListField ), который содержит элементы с одним атрибутом непосредственно в коллекцию строк?

{
    "FieldString":"string field",
    "FieldBool":false,
    "FieldId":"2513d3e3-3e1d-409d-b5a0-58eaa7cd6da9",
    "ListField":[
        {
            "Name":"string field 1"
        },
        {
            "Name":"string field 2"
        },
    ]
}
public class ClassName
{
    public string FieldString;
    public bool FieldBool;
    public Guid FieldId;
    public ICollection<string> ListField;
}

Я десериализирую большинство строк JSON, используя JsonConvert.DeserializeObject<ClassName>(jsonString);. Но чтобы сделать это здесь, мне нужно создать дополнительный класс со строковым атрибутом Name , как показано ниже, и использовать public ICollection<ListFieldItem> ListField; вместо строки.

public class ListFieldItem
{
    public string Name;
}

Я действительно хочу по возможности избегать использования класса с одним атрибутом.

Ответы [ 3 ]

4 голосов
/ 19 марта 2020

Вы можете использовать одно из следующих:

Пример:

public class ClassName
{
    [JsonConstructor]
    private ClassName(List<IDictionary> listField)
    {
        ListField = listField.Select(x => x["Name"].ToString()).ToArray();
    }

    public string FieldString;
    public bool FieldBool;
    public Guid FieldId;
    public ICollection<string> ListField;
}
0 голосов
/ 19 марта 2020

Чтобы расширить @ weichch ответ , если вы хотите решить эту проблему с помощью пользовательского JsonConverter, вот как может выглядеть код для этого:

public class ListOfNamesConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(ICollection<string>).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return JArray.Load(reader)
                     .Children<JObject>()
                     .Select(jo => (string)jo["Name"])
                     .ToList();
    }

    public override bool CanWrite => false;

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

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

    [JsonConverter(typeof(ListOfNamesConverter))]
    public ICollection<string> ListField;

Рабочая демонстрация здесь: https://dotnetfiddle.net/0VtxDo

0 голосов
/ 19 марта 2020

Я действительно хочу по возможности избежать использования класса с одним атрибутом.

это можно сделать так, как сказал @weichch

, однако посмотрите на json.

    "ListField":[
        {
            "Name":"string field 1"
        },
        {
            "Name":"string field 2"
        },
    ]

Содержит список объектов в ListField. На данный момент ListFieldItem имеет единственное свойство Name. В следующей версии API вы можете получить расширенный тип ListFieldItem с дополнительными свойствами, такими как Weight, BirthDate и т. Д.

Так что вам придется делать сильные модификации исходного кода, чтобы перейти к следующему API версия.

Вы можете создать ListFieldItem, несмотря на то, что это скучно или занимает дополнительное место;) в вашем проекте.

Дополнительно (если вас интересует только список имен), вы можете предоставить Расширение ClassName, которое извлекает значения ListFieldItem.Name в IEnumerable<string>, например

public static class ClassNameExt
{
 public IEnumerable<string> GetItemNames(this ClassName value)
 {
  return value.ListField.Select(_ => _.Name);
 }
}

. Это даст вам четкие типы ClassName и ListFieldItem, которые можно легко настроить (вами или другим лицом). Разработчик в вашей команде) со следующей версией API.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...