C#Newtonsoft JSON,处理可能包含数组或对象的响应

时间:2018-10-28 09:37:35

标签: c# json json.net

尝试解释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)更改为List,例如List从JSON数组反序列化。还可以将JsonArrayAttribute添加到类型中,以强制其从JSON数组反序列化。

2 个答案:

答案 0 :(得分:0)

我已解决此特定问题。

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

任何人都有一个更好的答案,这不是像这样的黑手党创可贴修复吗?

答案 1 :(得分:0)

您需要一个一个地检查响应,并根据其内容进行不同的处理。

您可以动态加载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