防止Json.NET将字符串数组反序列化为键值对的数组

时间:2015-09-22 20:14:25

标签: c# json json.net

JsonConvert.DeserializeObject成功将['a','b']反序列化为List<KeyValuePair<string, object>>。我希望它失败,只有当输入字符串类似于[{'Key':'a','Value':'b'}]时才会成功。

有没有办法实现这个目标?

1 个答案:

答案 0 :(得分:0)

看来你可能在Json.NET的KeyValuePairConverter中发现了一个错误,即它假定读者位于JSON对象的开头,而不是检查和验证它​​是否存在。如果你愿意,你可以report an issue on it

与此同时,以下JsonConverter会为您的案例正确抛出JsonException

public class KeyValueConverter : JsonConverter
{
    interface IToKeyValuePair
    {
        object ToKeyValuePair();
    }

    struct Pair<TKey, TValue> : IToKeyValuePair
    {
        public TKey Key { get; set; }
        public TValue Value { get; set; }

        public object ToKeyValuePair()
        {
            return new KeyValuePair<TKey, TValue>(Key, Value);
        }
    }

    public override bool CanConvert(Type objectType)
    {
        bool isNullable = (Nullable.GetUnderlyingType(objectType) != null);
        Type type = (Nullable.GetUnderlyingType(objectType) ?? objectType);

        return type.IsGenericType
            && type.GetGenericTypeDefinition() == typeof(KeyValuePair<,>);
    }

    public override bool CanWrite { get { return false; } } // Use Json.NET's writer.

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        bool isNullable = (Nullable.GetUnderlyingType(objectType) != null);
        Type type = (Nullable.GetUnderlyingType(objectType) ?? objectType);

        if (isNullable && reader.TokenType == JsonToken.Null)
            return null;

        if (type.IsGenericType
            && type.GetGenericTypeDefinition() == typeof(KeyValuePair<,>))
        {
            var pairType = typeof(Pair<,>).MakeGenericType(type.GetGenericArguments());
            var pair = serializer.Deserialize(reader, pairType);
            if (pair == null)
                return null;
            return ((IToKeyValuePair)pair).ToKeyValuePair();
        }
        else
        {
            throw new JsonSerializationException("Invalid type: " + objectType);
        }
    }

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

然后使用它:

        string json = @"['a','b']";

        var settings = new JsonSerializerSettings { Converters = new JsonConverter[] { new KeyValueConverter() } };
        var list = JsonConvert.DeserializeObject<List<KeyValuePair<string, object>>>(json, settings);

示例fiddle

<强>更新

要在JSON包含不存在的属性时强制执行错误,请使用JsonSerializerSettings.MissingMemberHandling = MissingMemberHandling.Error

        var settings = new JsonSerializerSettings
        {
            MissingMemberHandling = MissingMemberHandling.Error,
            Converters = new JsonConverter[] { new KeyValueConverter() },
        };