8

我们有一些 JSON 正在反序列化为 C# 中的强类型对象图。但是,我们遇到了一个问题:有时 JSON 中的一个“空”值(例如,空字符串)在映射到我们模型中的布尔值的属性中。

在我们的例子中,我们知道 100% 的时间,我们可以将这些“空白”值转换为 Boolean false

但是,我尝试过的 JSON 反序列化器并不知道这一点(可以理解)。

我一直在尝试找到一种方法来拦截每个属性的反序列化,并可选择覆盖输出。即,如果有一个我可以注册的“拦截器”方法,它看起来像这样:

    public Boolean JsonDeserializationInterceptor(String rawJson, System.Type targetType, out object result)
    {
        Boolean overrodeValue = false;
        result = null;
        if(targetType == typeof(System.Boolean))
        {
            overrodeValue = true;
            // We'll pretend that we're interpreting the string "Yes" as
            // true, and all other values are false.
            if (rawJson != null && rawJson.ToLower() == "\"yes\"")
                result = true;
            else
                result = false;
        }

        return overrodeValue;
    }

当然,这只是假设,但希望它能让您了解我想要完成的工作。

在我的研究中,我无法找到一种方法来做到这一点。我看过Json.NETSystem.Runtime.Serialization.Json.DataContractJsonSerializerSystem.Web.Script.Serialization.JavaScriptSerializer。我敢打赌有一种方法可以做到这一点,而我只是无法弄清楚。

编辑:我认为您可能可以使用JsonConverterAttribute,但到目前为止我还无法使其正常工作。

4

2 回答 2

6

为原始类型编写自定义JsonConverter非常简单:

using System;
using Newtonsoft.Json;

namespace So16972364JsonDeserializeConverter
{
    class BoolConverter : JsonConverter
    {
        public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
        {
            serializer.Serialize(writer, value);
        }

        public override object ReadJson (JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            switch (reader.TokenType) {
                case JsonToken.String:
                    if ((string)reader.Value == "")
                        return false;
                    break;
                case JsonToken.Boolean:
                    return reader.Value;
            }
            throw new JsonReaderException("Expected boolean or empty string.");
        }

        public override bool CanConvert (Type objectType)
        {
            return objectType == typeof(bool);
        }
    }

    class Program
    {
        const string json = @"
{
    b1: true,
    b2: false,
    b3: ''
}
";

        static void Main ()
        {
            Foo foo = JsonConvert.DeserializeObject<Foo>(json, new JsonSerializerSettings {
                Converters = { new BoolConverter() }
            });
            Console.WriteLine(JsonConvert.SerializeObject(foo, Formatting.Indented));
            Console.ReadKey();
        }
    }

    class Foo
    {
        public bool b1, b2, b3;
    }
}

此代码覆盖所有布尔值的反序列化。如果您仅对特定成员需要此功能,则需要申请JsonConverterAttribute.

于 2013-06-07T05:49:33.103 回答
3

上面的例子有一个错误。代替

public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
{
    serializer.Serialize(writer, value);
}

应该有

public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
{
    writer.WriteValue(value);
}

否则你会得到StackOverflow异常!奇怪的是为什么还没有人写过它。

于 2017-03-24T17:14:01.353 回答