【问题标题】:Handle Double.NaN from Java to C# using snakeyaml (Java) and YamlDotNet (C#)使用 snakeyaml (Java) 和 YamlDotNet (C#) 处理从 Java 到 C# 的 Double.NaN
【发布时间】:2015-12-20 20:36:54
【问题描述】:

我正在使用 YAML 在 C# GUI 和服务器端 Java 之间进行通信,这通常工作正常。但是,如果我在 Java 端传递一个 Double 字段并且值为 Double.NaN,则 Yaml 将作为“.NaN”传递,并且当我在 C# 端反序列化时,会抛出一个“System.FormatException”作为 C#需要字符串“NaN”[不是“.NaN”]。

有谁知道是否有办法拦截反序列化器,或者添加格式以便在 C# 端“.NaN”可以解析为双精度?

(我能想到的一种解决方法是在序列化为 YAML 之前将所有 NaN 更改为特殊值,然后在 C# 上识别特殊值并转换回 NaN,但这似乎是一个很大的 hack。)

【问题讨论】:

  • 我发现了这个link,并注意到在应用以下工作后:Double.Parse(".NaN"),但似乎 YamlDotNet 创建了它自己的 NumberFormatInfo link,所以我猜真正的问题是如何覆盖 YamlDotNet 中使用的 NumberFormatInfo。有什么想法吗?

标签: snakeyaml yamldotnet


【解决方案1】:

这似乎是 YamlDotNet 处理浮点数的方式中的一个错误。在它修复之前,您可以通过注册一个自定义节点 INodeDeserializer 来解决它,该节点将处理这些特殊情况。

下面是这种反序列化器的快速而简单的实现:

public class FloatNodeDeserializer : INodeDeserializer
{
    private static readonly Dictionary<Tuple<Type, string>, object> SpecialFloats =
        new Dictionary<Tuple<Type, string>, object>
    {
        { Tuple.Create(typeof(float), ".nan"), float.NaN },
        { Tuple.Create(typeof(float), ".inf"), float.PositiveInfinity },
        { Tuple.Create(typeof(float), "-.inf"), float.NegativeInfinity },

        { Tuple.Create(typeof(double), ".nan"), double.NaN },
        { Tuple.Create(typeof(double), ".inf"), double.PositiveInfinity },
        { Tuple.Create(typeof(double), "-.inf"), double.NegativeInfinity },
    };

    bool INodeDeserializer.Deserialize(
        EventReader reader,
        Type expectedType,
        Func<EventReader, Type, object> nestedObjectDeserializer,
        out object value
    ) {
        var scalar = reader.Peek<Scalar>();
        if (scalar == null) {
            value = null;
            return false;
        }

        var found = SpecialFloats.TryGetValue(
            Tuple.Create(expectedType, scalar.Value),
            out value);

        if(found) {
            reader.Allow<Scalar>();
        }
        return found;
    }
}

注册方式为:

var deserializer = new Deserializer();
deserializer.NodeDeserializers.Insert(0, new FloatNodeDeserializer());

See a fully working fiddle here

【讨论】:

  • 太棒了!谢谢安托万。仅供参考,我不得不对 FloatNodeDeserializer 进行非常小的改动。从字典中获取时,我将 scalar.Value.ToLower() 作为值是 .NaN,因此找不到 .nan。感谢您的快速响应!
猜你喜欢
  • 2018-12-26
  • 2014-06-02
  • 2011-07-21
  • 2011-07-22
  • 2011-12-15
  • 1970-01-01
  • 1970-01-01
  • 2013-01-04
  • 2023-03-22
相关资源
最近更新 更多