反序列化包含单个或对象数组的JSON [英] Deserializing JSON containing single or array of objects

查看:156
本文介绍了反序列化包含单个或对象数组的JSON的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试反序列化包含图像URL的事件数据.

I'm trying to deserialize event data that includes image urls.

当事件包含单个图像时,JSON字符串的格式为:

When the event includes a single image, the format of the JSON string is:

"images": {
  "image": {
      "small": {...},
      "width": "48",
      "creator": null,
      "thumb": {...},
      "height": "48",
      "url": "http://example.com/image1.jpeg",
      "medium": {...},
      "id": "1"
    }
}

当有多个图像可用时,响应的格式更改为:

When multiple images are available, the format of the response changes to:

"images": {
    "image": [
      {
        "small": {...},
        "width": "48",
        "creator": null,
        "thumb": {...},
        "height": "48",
        "url": "http://example.com/image1.jpeg",
        "medium": {...},
        "id": "1"
      },
      {
        "small": {...},
        "width": "48",
        "creator": null,
        "thumb": {...},
        "height": "48",
        "url": "http://example.com/image2.jpeg",
        "medium": {...},
        "id": "2"
      }
    ]
  }

当我尝试反序列化时,我可以使一个或其他模型起作用,但不能同时使两个模型起作用.

When I'm trying to deserialize, I can get one or other model to work, but not both at the same time.

我的模型是这样的:

public class Event
{
    public string id { get; set; }
    public string imageId { get; set; }
    public Image image { get; set; }
    public Images images { get; set; }
}

public class Image
{
    public string id { get; set; }
    public string width { get; set; }
    public string caption { get; set; }
    public string url { get; set; }
    public string height { get; set; }
    public int smallId { get; set; }
    public Small small { get; set; }
    public int mediumId { get; set; }
    public Medium medium { get; set; }
    public int thumbId { get; set; }
    public Thumb thumb { get; set; }
}

如果按以下方式定义我的Images类,则它可以与数组一起使用:

If I define my Images class as follows, it works with arrays:

public class Images
{
    public string id { get; set; }
    public List<Image> image { get; set; }
}

如果我将其定义如下,则它适用于单个图像:

If I define it as follows, it works with single images:

public class Images
{
    public string id { get; set; }
    public Image image { get; set; }
}

从理论上讲,我可以在Images类中同时包含一个List和一个Image,但是我不能同时使用相同的名称,并且如果我更改任何一个名称,反序列化都将无效.

In theory, I could contain both a List and an Image in the Images class, but I can't use the same name for both and the deserialization doesn't work if I change either name.

我知道这两个响应都是有效的JSON(它们代表了它们的预期值),但这是一个不好的实现吗?

I understand that both responses are valid JSON (they represent what they're supposed to), but is this a bad implementation?

还是我在模型/反序列化中缺少一些可以让我反序列化单个对象和数组的东西?

Or am I missing something in my model/deserialization that should allow me to deserialize both the single object and array?

谢谢.

更新 反序列化代码:

var feedUrl = url;
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));

var serializer = new DataContractJsonSerializer(typeof(EventDetail));

var streamTask = client.GetStreamAsync(feedUrl);
EventDetail eventDetail = serializer.ReadObject(await streamTask) as EventDetail;

return eventDetail;

推荐答案

过去曾问过类似的问题:"

Similar question was asked in the past: "How to handle both a single item and an array for the same property using JSON.net". The approach is basically to use customConverter as follow:

public class Images
{
    [JsonProperty("id")]
    public string Id { get; set; }

    [JsonProperty("image")]
    [JsonConverter(typeof(SingleOrArrayConverter<Image>))]
    public List<Image> Image { get; set; }
}


public class SingleOrArrayConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(List<T>));
    }

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

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

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

这篇关于反序列化包含单个或对象数组的JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆