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

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

是否有办法实现这一点?


1
@xsquared,你能发一下验证任何JSON的正则表达式吗? - Eser
1
@user2864740,您能否发表一条真正的评论,而不是嘲笑我的英语? - Eser
@user2864740,好的,那你是什么意思呢? - Eser
@Eser 这只是一个迂腐的文字游戏,我已经删除了,因为它毫无意义;“any”的两种解读都是正确的。 - user2864740
对于我昨天的正则表达式建议,我很抱歉,当时我没有认真听。 - x squared
显示剩余2条评论
1个回答

0

看起来您可能在 Json.NET 的 KeyValuePairConverter 中发现了一个错误,即它假设读取器位于 JSON 对象的开头,而没有检查和验证位置是否正确。如果您愿意,您可以报告此问题

与此同时,以下 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() },
        };

谢谢,这使得"['a','b']"的失败符合预期。然而,对于以下情况仍然成功,它们似乎也应该失败:[{'a':'b','c':'d'}](因为其字段未命名为Key和Value)和"[{'Key':{'x':1},'Value':false}]"(因为键不是字符串)。您有任何想法以通用方式解决这个问题吗(而不是硬编码转换器为<sring,object>)? - joshs8080

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接