Как десериализовать весь ответ, который может быть массивом или отдельным объектом? - PullRequest
1 голос
/ 18 октября 2019

У меня есть ситуация, когда ответ от API может содержать либо массив, либо отдельный элемент. Однако я борюсь с десериализацией ответов из-за ответа массива, содержащего другой вложенный объект. Вот различные ответы, которые могут быть возвращены (образец).

Это формат ответа, когда возвращается список элементов

{
  "data": {
    "items": [
       {
          "id": 1
       },
       {
          "id": 2
       }
    ]
  }
}

Это ответ, который отправляется, когдавозвращается один элемент

{
  "data": {
    "id": 1
  }
}

Моя первоначальная попытка стандартизировать ответ включала создание настраиваемого атрибута преобразователя, но проблема в том, что вы не можете передать в него универсальный параметр. Код для ReadJson приведен ниже:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    JToken token = JToken.Load(reader);
    if(token["items"]?.Type == JTokenType.Array)
    {
        return token["items"].ToObject<T>();
    }

    return new List<T>() { token.ToObject<T>() };
}

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

public  class Response<T>
{
    [JsonProperty("version")]
    public string Version { get; set; }

    [JsonConverter(SingleOrArrayConverter<T>)]
    public T Data { get; set; }

    [JsonProperty("_links")]
    public Links Links { get; set; }
}

У кого-нибудь есть другие мысли / решения этой проблемы?

1 Ответ

0 голосов
/ 18 октября 2019

Имеется несколько классов, как показано ниже:

        public class Response
        {
            [JsonProperty("data")]
            public Data ResponseData { get; set; }
        }
        public class Data
        {
            [JsonProperty("id",NullValueHandling = NullValueHandling.Ignore)]
            public long? Id { get; set; }
            [JsonProperty("items", NullValueHandling = NullValueHandling.Ignore)]
            public List<Item> Items { get; set; }
        }
        public class Item
        {
            public long? Id { get; set; }
        }

Затем десериализуйте ответ, как показано ниже:

var responseObject = Newtonsoft.Json.JsonConvert.DeserializeObject<Response>(responseString);

Чтобы еще больше улучшить доступ к элементам данных, добавьте свойство ниже кКласс данных:

public List<Item> ResponseItems
            => Id != null
            ? new List<Item>(new Item[] { new Item { Id = Id} })
            : Items;
...