反序列化时如何忽略JSON对象数组中的空白数组? [英] How can I ignore a blank array inside an array of JSON objects while deserializing?

查看:241
本文介绍了反序列化时如何忽略JSON对象数组中的空白数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Json.NET反序列化JSON.我如何忽略反序列化期间在对象数组内部意外出现的空白数组?

I am deserializing JSON using Json.NET. How can I ignore a blank array that unexpectedly occurs inside an array of objects during deserialization?

我已经在此网站上从第三方测试了以下JSON http://json.parser.online .fr/确认其格式正确:

I have tested the following JSON from a third party on this website http://json.parser.online.fr/ which confirm that it is well-formed:

{
  "total_events": 3551574,
  "json.appID": [
    {
      "count": 3551024,
      "term": 1
    },
    {
      "count": 256,
      "term": 2
    },
    []                /* <----- I need to ignore this empty array */
  ],
  "unique_field_count": 2
}

我想将其反序列化为以下模型:

I would like to deserialize it to the following model:

public class RootObject
{
    [JsonProperty("total_events")]
    public int TotalEvents { get; set; }

    [JsonProperty("json.appID")]
    public List<JsonAppID> AppIds { get; set; }

    [JsonProperty("unique_field_count")]
    public int UniqueFieldCount { get; set; }
}

public class JsonAppID
{
    [JsonProperty(PropertyName = "count")]
    public int Count { get; set; }

    [JsonProperty(PropertyName = "term")]
    public string Term { get; set; }
}

但是当我尝试时,出现以下异常:

But when I try, I get the following exception:

Newtonsoft.Json.JsonSerializationException:无法将当前JSON数组(例如[1,2,3])反序列化为类型"JsonAppID",因为该类型需要一个JSON对象(例如{"name":"value"})正确反序列化.
要解决此错误,请将JSON更改为JSON对象(例如{"name":"value"}),或将反序列化类型更改为数组或实现集合接口的类型(例如ICollection,IList),例如可以从JSON数组反序列化的列表.还可以将JsonArrayAttribute添加到类型中,以强制其从JSON数组反序列化.
路径'[''json.appID'] [2]',第12行,位置6.

Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'JsonAppID' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path '['json.appID'][2]', line 12, position 6.

如何忽略"json.appID"数组中不需要的空数组并成功反序列化我的模型?

How can I ignore the unneeded empty array inside the "json.appID" array and successfully deserialize my model?

推荐答案

当预期的 JSON 值类型(对象,数组或基元)与观察到的类型不匹配.在您的情况下,您的JsonAppID类型对应于一个JSON对象-一组无序的名称/值对,以{(左括号)开始,以}(右括号)结束.当遇到数组时,将抛出您看到的异常.

Json.NET will throw an exception when the expected JSON value type (object, array or primitive) does not match the observed type. In your case your JsonAppID type corresponds to a JSON object - an unordered set of name/value pairs which begins with { (left brace) and ends with } (right brace). When an array is encountered instead the exception you see is thrown.

如果您希望静默跳过对象数组中的无效值类型,则可以引入

If you would prefer to silently skip invalid value types in an array of objects, you could introduce a custom JsonConverter for ICollection<T> which does just that:

public class TolerantObjectCollectionConverter<TItem> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return !objectType.IsArray && objectType != typeof(string) && typeof(ICollection<TItem>).IsAssignableFrom(objectType);
    }

    public override bool CanWrite { get { return false; } }

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // Get contract information
        var contract = serializer.ContractResolver.ResolveContract(objectType) as JsonArrayContract;
        if (contract == null || contract.IsMultidimensionalArray || objectType.IsArray)
            throw new JsonSerializationException(string.Format("Invalid array contract for {0}", objectType));

        // Process the first token
        var tokenType = reader.SkipComments().TokenType;
        if (tokenType == JsonToken.Null)
            return null;
        if (tokenType != JsonToken.StartArray)
            throw new JsonSerializationException(string.Format("Expected {0}, encountered {1} at path {2}", JsonToken.StartArray, reader.TokenType, reader.Path));

        // Allocate the collection
        var collection = existingValue as ICollection<TItem> ?? (ICollection<TItem>)contract.DefaultCreator();

        // Process the collection items
        while (reader.Read())
        {
            switch (reader.TokenType)
            {
                case JsonToken.EndArray:
                    return collection;

                case JsonToken.StartObject:
                case JsonToken.Null:
                    collection.Add(serializer.Deserialize<TItem>(reader));
                    break;

                default:
                    reader.Skip();
                    break;
            }
        }
        // Should not come here.
        throw new JsonSerializationException("Unclosed array at path: " + reader.Path);
    }
}

public static partial class JsonExtensions
{
    public static JsonReader SkipComments(this JsonReader reader)
    {
        while (reader.TokenType == JsonToken.Comment && reader.Read())
            ;
        return reader;
    }
}

然后将其应用于您的数据模型,如下所示:

Then apply it to your data model as follows:

public class JsonAppID
{
    [JsonProperty(PropertyName = "count")]
    public int Count { get; set; }

    [JsonProperty(PropertyName = "term")]
    public string Term { get; set; }
}

public class RootObject
{
    [JsonProperty("total_events")]
    public int TotalEvents { get; set; }

    [JsonProperty("json.appID")]
    [JsonConverter(typeof(TolerantObjectCollectionConverter<JsonAppID>))]
    public List<JsonAppID> AppIds { get; set; }

    [JsonProperty("unique_field_count")]
    public int UniqueFieldCount { get; set; }
}

示例工作 .Net小提琴.

这篇关于反序列化时如何忽略JSON对象数组中的空白数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆