【问题标题】:Deserializing JSON containing single or array of objects [duplicate]反序列化包含单个或对象数组的 JSON [重复]
【发布时间】:2017-12-04 07:52:44
【问题描述】:

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

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

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

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

"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"
      }
    ]
  }

当我尝试反序列化时,我可以让一个或其他模型工作,但不能同时工作。

我的模型是这样的:

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 类,它适用于数组:

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

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

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

理论上,我可以在 Images 类中同时包含 List 和 Image,但我不能对两者使用相同的名称,并且如果我更改任何一个名称,反序列化将不起作用。

我知道这两个响应都是有效的 JSON(它们代表他们应该做的),但这是一个糟糕的实现吗?

或者我是否在我的模型/反序列化中遗漏了一些应该允许我反序列化单个对象和数组的东西?

谢谢。

更新 反序列化代码:

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;

【问题讨论】:

  • 请同时发布您的序列化/反序列化代码。希望它能帮助我们了解您的问题。

标签: c# json asp.net-mvc .net-core


【解决方案1】:

过去有人问过类似的问题:“How to handle both a single item and an array for the same property using JSON.net”。该方法基本上是使用customConverter如下:

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();
    }
}

【讨论】:

  • 谢谢@hsoesanto - 这是完全相同的问题。我搜索的时候没找到。
  • 虽然图像定义不应该如下: public class Images { [JsonProperty("id")] public string Id { get;放; } [JsonProperty("image")] [JsonConverter(typeof(SingleOrArrayConverter))] public List Image { get;放; } }
  • @PaulM 对不起,你是对的。之前编辑的时候错过了。现在已修复。很高兴它有帮助 =)
【解决方案2】:

没有看到您的序列化/反序列化代码,我认为问题就在那里。

如果您只有一个 Image,则另一种解决方案可能是发送一个空的图像列表 (Images),反之亦然。所以你的 JSON 中总是有ImageImages

【讨论】:

    猜你喜欢
    • 2015-06-11
    • 1970-01-01
    • 1970-01-01
    • 2022-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多