How can I ignore a blank array inside an array of JSON objects while deserializing?

前端 未结 1 987
青春惊慌失措
青春惊慌失措 2021-01-26 23:55

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

相关标签:
1条回答
  • 2021-01-27 00:38

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

    Sample working .Net fiddle.

    0 讨论(0)
提交回复
热议问题