【问题标题】:Serialize NaN values into JSON as nulls in JSON.NET在 JSON.NET 中将 NaN 值序列化为 JSON 作为空值
【发布时间】:2011-12-10 11:37:48
【问题描述】:

大多数 Json 解析器不会序列化 NaN,因为在 Javascript 中,NaN 不是常量。然而,Json.Net 确实将 NaN 值序列化为 NaN,这意味着它会输出无效的 Json;大多数解析器尝试反序列化此 Json 将失败。 (我们在 WebKit 中反序列化。)

我们已经破解了 Json.Net 代码以在传递 NaN 时输出空值,但这似乎是一个糟糕的解决方案。 Douglas Crockford(曾经)建议使用空值代替 NaN:

http://www.json.org/json.ppt(看幻灯片 16)

显然,这并不适用于所有情况,但对于我们的目的来说是可以的。我们宁愿不必修改 Json.Net 的源代码。有谁知道如何使用 Json.Net 将 NaN 输入转换为空输出?

【问题讨论】:

    标签: .net json serialization json.net nan


    【解决方案1】:

    作者advises us 到“如果这对您很重要,请为 float/double 编写一个 JsonConverter 以使 NaN 安全”,因此您可以这样做:

    class LawAbidingFloatConverter : JsonConverter {
        public override bool CanRead
        {
            get
            {
                return false;
            }
        }
        public override bool CanWrite
        {
            get
            {
                return true;
            }
        }
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var val = value as double? ?? (double?) (value as float?);
            if (val == null || Double.IsNaN((double)val) || Double.IsInfinity((double)val))
            {
                writer.WriteNull();
                return;
            }
            writer.WriteValue((double)val);
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(double) || objectType == typeof(float);
        }
    }
    

    然后使用它:

    var settings = new JsonSerializerSettings();
    var floatConverter = new LawAbidingFloatConverter();
    settings.Converters.Add(floatConverter);
    var myConverter = new JsonNetSerializer(settings);
    

    【讨论】:

    • 不适用于double AND float - <float-value> as double? 总是 null!
    • 你是对的,它不适用于floats。我不确定为什么 (double?) value 在 value 是浮点数时会产生 null(double?) (float?) value 没问题。我已经用一个可行的解决方案更新了我的答案。谢谢!
    【解决方案2】:

    带有float 支持的Raphael Schweikerts 解决方案:

    public class StandardFloatConverter : JsonConverter
    {
        public override bool CanRead
        {
            get
            {
                return false;
            }
        }
        public override bool CanWrite
        {
            get
            {
                return true;
            }
        }
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (value == null)
            {
                writer.WriteNull();
                return;
            }
    
            var val = Convert.ToDouble(value);
            if(Double.IsNaN(val) || Double.IsInfinity(val))
            {
                writer.WriteNull();
                return;
            }
            // Preserve the type, otherwise values such as 3.14f may suddenly be
            // printed as 3.1400001049041748.
            if (value is float)
                writer.WriteValue((float)value);
            else
                writer.WriteValue((double)value);
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(double) || objectType == typeof(float);
        }
    }
    

    【讨论】:

    • 如果保留正常值的原始行为很重要,也可以将write.WriteValue(val) 替换为if (value is float) writer.WriteValue((float)val); else writer.WriteValue((double)val)。否则,突然3.14f 可能会被序列化为3.1400001049041748 而不是3.14。这破坏了我的应用程序中的一个单元测试。
    • 感谢您指出这一点,但我不能再接受您的编辑(已被拒绝!?)...我根据您的编辑更改了答案。
    【解决方案3】:

    为了未来的读者,如果您可以接受零而不是空值Json.Net 似乎已经解决了这个问题。

    序列化 NaN 和无穷大浮点值

    Json.NET 不再序列化 NaN 和正负无穷大 浮点值作为符号,这是无效的 JSON。随着 5.0 新的默认值是将这些值序列化为字符串,例如“南” 而不是 NaN。序列化正常浮动没有变化 点数。

    已添加 FloatFormatHandling 设置,以便您控制如何 NaN 和无穷大值被序列化。

    string json;     
    IList<double> d = new List<double> {1.1, double.NaN, double.PositiveInfinity};
    
    json = JsonConvert.SerializeObject(d);
    
    // [1.1,"NaN","Infinity"]
    
    json = JsonConvert.SerializeObject(d, new JsonSerializerSettings {FloatFormatHandling = FloatFormatHandling.Symbol});  
    
    // [1.1,NaN,Infinity]
    
    json = JsonConvert.SerializeObject(d, new JsonSerializerSettings {FloatFormatHandling = FloatFormatHandling.DefaultValue});  
    
    // [1.1,0.0,0.0]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-22
      • 1970-01-01
      • 1970-01-01
      • 2019-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多