9

我有一些.NET代码可以反序列JSON化由webservice运行动态语言创建的对象。因为源是动态的,它有时会以浮点格式序列化整数值(例如,2 被序列化为“2.0”)。

使用Json.NET 4.0.4,这可以无缝地工作(似乎在反序列化时应用了舍入)。Json.NET 4.5但是,随着升级到FormatException. 这是代码:

// works as expected in both versions
var s = "2";
Console.WriteLine(JsonConvert.DeserializeObject<int>(s));

// throws FormatException in 4.5 only
var s = "2.0";
Console.WriteLine(JsonConvert.DeserializeObject<int>(s));

// throws FormatException in 4.5, rounds to 3 in 4.0.4
var s = "2.6";
Console.WriteLine(JsonConvert.DeserializeObject<int>(s));

有什么简单的方法可以恢复原始行为吗?理想的行为是只反序列化具有整数值的数字,但可以采用任何格式(例如 2.0、1e10,但不是 2.5),但我会满足于 4.0.4 的行为。

4

1 回答 1

6

您可以通过自定义JsonConverter处理四舍五入(或丢弃)十进制值来做到这一点。它可能看起来像这样:

class CustomIntConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(int));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JValue jsonValue = serializer.Deserialize<JValue>(reader);

        if (jsonValue.Type == JTokenType.Float)
        {
            return (int)Math.Round(jsonValue.Value<double>());
        }
        else if (jsonValue.Type == JTokenType.Integer)
        {
            return jsonValue.Value<int>();
        }

        throw new FormatException();
    }

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

然后,您可以像这样使用自定义转换器:

JsonSerializerSettings settings = new JsonSerializerSettings 
{
    Converters = new List<JsonConverter> { new CustomIntConverter() } 
};

string json = @"[2.6, 0, 4.1, 5, -3, -2.2]";

List<int> list = JsonConvert.DeserializeObject<List<int>>(json, settings);

foreach (int val in list)
{
    Console.WriteLine(val);
}

上面的输出将是这样的:

3
0
4
5
-3
-2

如果您希望转换器忽略十进制值而不是四舍五入,请替换以下代码行

        return (int)Math.Round(jsonValue.Value<double>());

有了这个:

        return (existingValue ?? default(int));

进行该更改后,上面的测试代码的输出将如下所示:

0
0
0
5
-3
0
于 2013-07-19T15:20:51.847 回答