Десериализация массива объектов JSON, но когда массив содержит 1 объект, массив опускается - PullRequest
0 голосов
/ 15 февраля 2019

Я использую API с .NET Core, который возвращает массивы объектов.Но когда массив содержит только один объект, внешний API удалит массив и вставит объект напрямую.

Я надеюсь, что есть атрибут или параметр, который не требует от меня работы с JObjects или переопределенияJsonConverter.

Пример JSON, с которым я имею дело:

{
    "a": {
        "b": [{
            "id": 1,
            "name": "first object"
        }, {
            "id": 2,
            "name": "second object"
        }]
    }
}

Json с пропущенным массивом

{
    "a": {
        "b": {
            "id": 1,
            "name": "One object only"
        }
    }
}

Это то, что я делаю (упрощенно)

public class Response
{
    public A a { get; set; }
}

public class A
{
    public List<B> b { get; set; }
}

public class B
{
    public int id { get; set; }
    public string name { get; set; }
}

var apiResponse = await response.Content.ReadAsAsync<Response>()

Хотелось бы, чтобы при возвращении второго примера JSON функция ReadAsAsync () автоматически понимала, что он должен быть преобразован в массив с одним объектом из B.

Проблема заключается в том, чтоэто может происходить во многих местах в ответах API.

1 Ответ

0 голосов
/ 15 февраля 2019

Вы можете создать собственный JsonConverter, чтобы проверить, имеете ли вы дело с массивом или отдельным объектом.В следующем примере показан конвертер, который преобразуется в List<T>:

public class ArrayJsonConverter<T> : JsonConverter<List<T>>
{
    public override List<T> ReadJson(JsonReader reader, Type objectType, List<T> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.StartObject)
        {
            var jObj = JObject.Load(reader);
            var obj = jObj.ToObject<T>();
            var lst = new List<T>();
            lst.Add(obj);
            return lst;
        }
        else if (reader.TokenType == JsonToken.StartArray)
        {
            var jArray = JArray.Load(reader);
            return jArray.ToObject<IEnumerable<T>>().ToList();
        }
        throw new InvalidOperationException();
    }

    public override void WriteJson(JsonWriter writer, List<T> value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Преобразователь сначала проверяет, находится ли считыватель на объекте или массиве.В зависимости от этого он либо создает список только с одним объектом, либо читает массив.
Чтобы использовать его, можно пометить свойства атрибутом JsonConverter, например:

public class A
{
    [JsonConverter(typeof(ArrayJsonConverter<B>))]
    public List<B> b { get; set; }
}
...