反序列化包含单个或对象数组的JSON [英] Deserializing JSON containing single or array of objects
问题描述
我正在尝试反序列化包含图像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屋!