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

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

问题描述

我正在尝试反序列化包含图片网址的事件数据.

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;

推荐答案

以前有人问过类似的问题:"如何使用 JSON.net 处理同一属性的单个项目和数组".该方法基本上是使用 customConverter 如下:

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天全站免登陆