5

我正在使用一个返回我需要反序列化的 json 对象的 API。我的问题是这些对象的成员之一有时是一个空数组(“[]”),有时是一个字典(“{“1”:{...},“2”:{...}}” )。我想将它反序列化为数组或字典,因为我不关心 ID,我只想要所有对象的列表。这是我反序列化对象的方法:

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

这是 Response 类的定义:

public class Response
{
    [JsonProperty(PropertyName = "variations")]
    public Dictionary<int, Variation> Variations { get; set; }
}

当 Response 在其变体字段中包含字典时,它工作得很好,但是当它包含一个空数组时它会失败。我从 Newtonsoft 收到一个错误,说不能将数组反序列化为字典。如果我将 Variations 属性定义为一个数组,它适用于空数组,但当它是一个字典时它会失败。我该怎么做才能正确反序列化两个可能的值,或者忽略空数组并将 Variations 设置为 null 当它是一个数组而不是失败时。

谢谢。

4

3 回答 3

8

这是使用 JsonConverter 的替代解决方案

public class Response
{
    [JsonProperty(PropertyName = "variations")]
    [JsonConverter(typeof(EmptyArrayOrDictionaryConverter))]
    public Dictionary<int, Variation> Variations { get; set; }
}


public class EmptyArrayOrDictionaryConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType.IsAssignableFrom(typeof(Dictionary<string, object>));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        if (token.Type == JTokenType.Object)
        {
            return token.ToObject(objectType, serializer);
        }
        else if (token.Type == JTokenType.Array)
        {
            if (!token.HasValues)
            {
                // create empty dictionary
                return Activator.CreateInstance(objectType);
            }
        }

        throw new JsonSerializationException("Object or empty array expected");
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }
}
于 2017-08-04T10:59:53.620 回答
2

这是 Carl 示例的变体(对不起,双关语)。我也有类似的需求,但我不需要返回字典,而是需要一个数组。我使用的 API 说它返回一个数组。但是,在结果中只有一项的情况下,它会作为对象返回!

public class VarationsContainer
{
    [JsonIgnore]
    public Varation[] Varations
    {
        get
        {
            return ParseObjectToArray<Variation>(VariationObject);
        }
    }

    [JsonProperty(PropertyName = "varations")]
    public object VarationsObject { get; set; }

    protected T[] ParseObjectToArray<T>(object ambiguousObject)
    {
        var json = ambiguousObject.ToString();
        if (String.IsNullOrWhiteSpace(json))
        {
            return new T[0]; // Could return null here instead.
        }
        else if (json.TrimStart().StartsWith("["))
        {
            return JsonConvert.DeserializeObject<T[]>(json);
        }
        else
        {
            return new T[1] { JsonConvert.DeserializeObject<T>(json) };
        }
    }
}

我希望这对其他一些悲伤的 API 消费者有用。

于 2013-09-14T20:39:11.900 回答
1

这是我使用的解决方案:

    public Dictionary<int, Variation> Variations
    {
        get
        {
            var json = this.VariationsJson.ToString();
            if (json.RemoveWhiteSpace() == EmptyJsonArray)
            {
                return new Dictionary<int, Variation>();
            }
            else
            {
                return JsonConvert.DeserializeObject<Dictionary<int, Variation>>(json);
            }
        }
    }

    [JsonProperty(PropertyName = "variations")]
    public object VariationsJson { get; set; }

基本上,变体首先在基本对象中反序列化。当我想读取值时,我检查对象是否为空数组,如果是,则返回一个空字典。如果对象是一个好的字典,我会反序列化它并返回它。

于 2012-09-04T16:08:47.893 回答