c#Newtonsoft.json DeserializeObject问题

时间:2018-03-05 11:21:12

标签: json.net

希望有人可以帮我解决我的问题。

我正在使用第三方API,根据后端产品的配置,它将返回不同的JSON结构作为响应。

我已经包含了JSON样本,根据产品显示了不同的结果。该产品的FreeGifts部分有3种情况:

  1. 有2个或更多免费礼物。
  2. 有1份免费礼物。
  3. 没有免费礼物
  4. 情景1

    {
        "FreeGifts": [{
            "FreeGift": [{
                    "SKU": "BOWS-SMALL-ALFIE"
                },
                {
                    "SKU": "BOWS-LARGE-ALONZO"
                },
                {
                    "SKU": "BOWS-LARGE-CLANCY"
                },
                {
                    "SKU": "BOWS-SMALL-ALVIN"
                },
                {
                    "SKU": "BOWS-SMALL-CLARK"
                }
            ]
        }]
    }
    

    情景2

    {
        "FreeGifts": [{
            "FreeGift": {
                "SKU": "BOWS-SMALL-ALVIN"
            }
        }]
    }
    

    情景3

    {
        "FreeGifts": [
            ""
        ]
    }
    

    http://json2csharp.com/https://jsonutils.com/等网站根据具体情况为我提供了3种不同的类定义。

    如果我在结构中只有其中一个,我可以处理它,但我有7或8左右。我不可能满足它。

    我完全不知道如何让Newtonsoft.json处理API产生的模糊性。

    我是否需要返回提供商并询问他们是否可以更改它?!?

2 个答案:

答案 0 :(得分:0)

您可以this answer使用SingleOrArrayConverter<FreeGift> {em} How to handle both a single item and an array for the same property using JSON.net TolerantObjectCollectionConverter<FreeGifts>以及Brian Rogerspublic class Root { [JsonConverter(typeof(TolerantObjectCollectionConverter<FreeGifts>))] public List<FreeGifts> FreeGifts { get; set; } } public class FreeGifts { [JsonConverter(typeof(SingleOrArrayConverter<FreeGift>))] public List<FreeGift> FreeGift { get; set; } } public class FreeGift { public string SKU { get; set; } } class SingleOrArrayConverter<T> : JsonConverter { // Taken from the answer to // https://stackoverflow.com/questions/18994685/how-to-handle-both-a-single-item-and-an-array-for-the-same-property-using-json-n // https://stackoverflow.com/a/18997172 // by Brian Rogers public override bool CanConvert(Type objectType) { return (objectType == typeof(List<T>)); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var tokenType = reader.SkipComments().TokenType; if (tokenType == JsonToken.Null) return null; var list = existingValue as List<T> ?? new List<T>(); if (tokenType == JsonToken.StartArray) { serializer.Populate(reader, list); } else { list.Add(serializer.Deserialize<T>(reader)); } return list; } public override bool CanWrite { get { return false; } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } } public class TolerantObjectCollectionConverter<TItem> : JsonConverter { // Taken from the answer to // https://stackoverflow.com/questions/49030516/how-can-i-ignore-a-blank-array-inside-an-array-of-json-objects-while-deserializi // https://stackoverflow.com/a/49078620/ 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; } } this answer 成功反序列化所有3个JSON变体。为此,请定义模型并应用相应的How can I ignore a blank array inside an array of JSON objects while deserializing?,如下所示:

[JsonConverter(typeof(TolerantObjectCollectionConverter<FreeGifts>))]

注意:

  • "FreeGifts": []处理上级[JsonConverter(typeof(SingleOrArrayConverter<FreeGift>))]数组有时可能包含不需要的字符串值的事实。简单地跳过该值。

  • "FreeGift"处理{{1}}属性值有时可能是单个对象或对象数组的事实。

  • 您可以在属性值可能是包含无效项的数组或数组中未包含的单个对象的情况下组合这两个转换器。但是,在所示的三个JSON示例中并非如此。

示例工作JSON converter

答案 1 :(得分:-1)

将其用作模型

public class FreeGift
{
    public string SKU { get; set; }
}

public class RootObject
{
    public List<FreeGift> FreeGifts { get; set; }
}

使用它来反序列化您的对象

private RootObject decomp(string content)
{
     var settings = new JsonSerializerSettings
            {
                DefaultValueHandling = DefaultValueHandling.Ignore,
                MissingMemberHandling = MissingMemberHandling.Ignore,
                NullValueHandling = NullValueHandling.Ignore
            };

     return JsonConvert.DeserializeObject<RootObject>(content, setting);
}