使用JSON.Net将JSON反序列化为对象或数组

时间:2022-08-23 08:10:22

I want to know if it is possible to deserialize a JSON object that could either be an object or an array.

我想知道是否可以反序列化可能是对象或数组的JSON对象。

Similar to this question: Jackson deserialize object or array

与此问题类似:杰克逊反序列化对象或数组

But using JSON.Net.

但是使用JSON.Net。

Example

{
    "response": {
        "status":"success",
        // Could be either a single object or an array of objects.
        "data": {
            "prop":"value"
        }
        // OR
        "data": [
            {"prop":"value"},
            {"prop":"value"}
        ]
    }
}

3 个解决方案

#1


2  

You can change the property type for "data" in your model to dynamic or an object and check if it is an array on run-time.

您可以将模型中“data”的属性类型更改为dynamic或object,并在运行时检查它是否为数组。

Here's an example:

这是一个例子:

public class Response
{
    [JsonProperty("status")]
    public string Status { get; set; }
    [JsonProperty("data")]
    public dynamic Data { get; set; }
}


var response = JsonConvert.DeserializeJson<Response>(json);
.
.
.

Type responseDataType = response.Data.GetType();

if(responseDataType.IsArray) {
    // It's an array, what to do?
}
else {
    // Not an array, what's next?
}

#2


3  

An alternative would be to write our JsonConverter and use it for deserializing so we can work with static types after conversion.

另一种方法是编写我们的JsonConverter并将其用于反序列化,以便我们可以在转换后使用静态类型。

class JsonDataConverter : JsonConverter
{
    public override bool CanWrite { get { return false; } }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Data);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var token = JToken.ReadFrom(reader);

        if (token is JArray)
            return new Data(token.Select(t => t["prop"].ToString()));
        if (token is JObject)
            return new Data(new[] { token["prop"].ToString() });
        throw new NotSupportedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

[JsonConverter(typeof(JsonDataConverter))]
class Data:List<string>
{
    public Data() : base() { }
    public Data(IEnumerable<string> data) : base(data) { }
}

class Response
{
    public string Status { get; set; }
    public Data Data { get; set; }
}

and an example:

一个例子:

    class Program
    {
        static void Main(string[] args)
        {
            var inputObj = @"{
                     'response': {
                        'status':'success',
                        // Could be either a single object or an array of objects.
                        'data': { 'prop':'value'}

                                 }
                             }";

            var inputArray = @"{
                     'response': {
                         'status':'success',
                         // Could be either a single object or an array of objects.
                         'data':[
                                   { 'prop':'value'},
                                   { 'prop':'value'}
                                ]
                                 }
                              }";

            var obj = JsonConvert.DeserializeAnonymousType(inputObj, new { Response = new Response() });

            foreach(var prop in obj.Response.Data)
                Console.WriteLine(prop);

            var arr = JsonConvert.DeserializeAnonymousType(inputArray, new { Response = new Response() });

            foreach (var prop in arr.Response.Data)
                Console.WriteLine(prop);
        }
}

#3


2  

I think this solves your problem

我认为这解决了你的问题

string jsonString= "your json string";
var token = JToken.Parse(jsonString);

if (token is JArray)
{
    IEnumerable<Car> cars= token.ToObject<List<Car>>();
}
else if (token is JObject)
{
    Car car= token.ToObject<Car>();
}

#1


2  

You can change the property type for "data" in your model to dynamic or an object and check if it is an array on run-time.

您可以将模型中“data”的属性类型更改为dynamic或object,并在运行时检查它是否为数组。

Here's an example:

这是一个例子:

public class Response
{
    [JsonProperty("status")]
    public string Status { get; set; }
    [JsonProperty("data")]
    public dynamic Data { get; set; }
}


var response = JsonConvert.DeserializeJson<Response>(json);
.
.
.

Type responseDataType = response.Data.GetType();

if(responseDataType.IsArray) {
    // It's an array, what to do?
}
else {
    // Not an array, what's next?
}

#2


3  

An alternative would be to write our JsonConverter and use it for deserializing so we can work with static types after conversion.

另一种方法是编写我们的JsonConverter并将其用于反序列化,以便我们可以在转换后使用静态类型。

class JsonDataConverter : JsonConverter
{
    public override bool CanWrite { get { return false; } }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Data);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var token = JToken.ReadFrom(reader);

        if (token is JArray)
            return new Data(token.Select(t => t["prop"].ToString()));
        if (token is JObject)
            return new Data(new[] { token["prop"].ToString() });
        throw new NotSupportedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

[JsonConverter(typeof(JsonDataConverter))]
class Data:List<string>
{
    public Data() : base() { }
    public Data(IEnumerable<string> data) : base(data) { }
}

class Response
{
    public string Status { get; set; }
    public Data Data { get; set; }
}

and an example:

一个例子:

    class Program
    {
        static void Main(string[] args)
        {
            var inputObj = @"{
                     'response': {
                        'status':'success',
                        // Could be either a single object or an array of objects.
                        'data': { 'prop':'value'}

                                 }
                             }";

            var inputArray = @"{
                     'response': {
                         'status':'success',
                         // Could be either a single object or an array of objects.
                         'data':[
                                   { 'prop':'value'},
                                   { 'prop':'value'}
                                ]
                                 }
                              }";

            var obj = JsonConvert.DeserializeAnonymousType(inputObj, new { Response = new Response() });

            foreach(var prop in obj.Response.Data)
                Console.WriteLine(prop);

            var arr = JsonConvert.DeserializeAnonymousType(inputArray, new { Response = new Response() });

            foreach (var prop in arr.Response.Data)
                Console.WriteLine(prop);
        }
}

#3


2  

I think this solves your problem

我认为这解决了你的问题

string jsonString= "your json string";
var token = JToken.Parse(jsonString);

if (token is JArray)
{
    IEnumerable<Car> cars= token.ToObject<List<Car>>();
}
else if (token is JObject)
{
    Car car= token.ToObject<Car>();
}