【问题标题】:C# Newtonsoft JSON, Handling a response which could contain an array or objectC# Newtonsoft JSON,处理可能包含数组或对象的响应
【发布时间】:2018-10-28 09:37:35
【问题描述】:

我在尝试用 C# 解释来自 API 服务器的响应时遇到了一点麻烦。

这是我们在纯 JSON 中得到的 API 响应;

[
    {
        "response" : { "test" : "Value" }
    },
    {
        "response" : []
    }
]

如何让 Newtonsoft JSON 处理这样的响应?

目前,我将“响应”对象作为模型,一旦 Newtonsoft 使用 JsonConvert.DeserialiseObject 处理内容,我就会收到以下错误。

Newtonsoft.Json.JsonSerializationException:无法将当前 JSON 数组(例如 [1,2,3])反序列化为类型“(已编辑)”,因为该类型需要 JSON 对象(例如 {"name":"value"} ) 以正确反序列化。 要修复此错误,请将 JSON 更改为 JSON 对象(例如 {"name":"value"})或将反序列化类型更改为数组或实现集合接口的类型(例如 ICollection、IList),例如可以从 JSON 数组反序列化。也可以将 JsonArrayAttribute 添加到类型中以强制它从 JSON 数组中反序列化。

【问题讨论】:

  • 你能添加你试图反序列化的代码
  • 请参考上面的帖子。它清楚地表明“响应”的值是具有值的对象或空数组。这是重新创建问题的方法,因为我无法(由于 NDA)分享您请求的特定信息。 :)

标签: c# json json.net


【解决方案1】:

您需要逐一检查响应,并根据它们的内容进行不同的处理。

您可以动态加载 JSON,然后根据加载的内容反序列化它们。

即对象反序列化为对象,数组反序列化为数组。

以下是您如何实现该目标的示例:

.Net Fiddle 这个工作。

using System;
using  Newtonsoft.Json.Linq;

public class Program
{
    public static void Main()
    {
        var json = "[{ \"response\" : { \"test\" : \"Value1\" } }, { \"response\" : [ { \"test\" : \"Value2\" }, { \"test\" : \"Value3\" }] }]";
        var responseContainers = JArray.Parse(json);

        foreach(var responseContainer in responseContainers)
        {
            var response = responseContainer.Value<JToken>("response");

            if(response.Type == JTokenType.Object)
            {
                var data = response.ToObject<Data>();
                Console.WriteLine("data: " + data.test);
            }
            else if(response.Type == JTokenType.Array)
            {
                var dataJArray = response.ToObject<JArray>();

                foreach(var dataJToken in dataJArray)
                {
                    var data = dataJToken.ToObject<Data>();
                    Console.WriteLine("datas: " + data.test);
                }
            }
        }
    }
}

public class Data
{
    public string test { get;set; }
}

输出:

data: Value1
datas: Value2
datas: Value3

或者,您可以使用此question 中的SingleOrArrayConverter

.Net Fiddle

using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;

public class Program
{
    public static void Main()
    {
        var json = "[{ \"response\" : { \"test\" : \"Value1\" } }, { \"response\" : [ { \"test\" : \"Value2\" }, { \"test\" : \"Value3\" }] }]";
        var items = JsonConvert.DeserializeObject<List<Item>>(json);

        foreach(var item in items)
        {
            var responses = item.response;

            Console.WriteLine("ResponseCount: " + responses.Count);

            foreach(var response in responses)
            {
                Console.WriteLine("response: " + response.test);
            }
        }
    }
}

public class Item
{
    [JsonConverter(typeof(SingleOrArrayConverter<Data>))]
    public List<Data> response { get;set; }
}

public class Data
{
    public string test { get;set; }
}

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

输出:

ResponseCount: 1
response: Value1
ResponseCount: 2
response: Value2
response: Value3

【讨论】:

    【解决方案2】:

    我已应用修复程序来处理此特定问题。

    通过将 .Replace("\"response\":[]","\"response\":{}") 添加到 JsonConverter 正在解释的字符串中。这只会修复检索到的代码中的这些特定事件。

    任何人有更好的答案,而不是像这样的一些黑客在一起的创可贴修复?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多