使用 snakeyaml (Java) 和 YamlDotNet (C#) 处理从 Java 到 C# 的 Double.NaN

Handle Double.NaN from Java to C# using snakeyaml (Java) and YamlDotNet (C#)

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

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

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

这似乎是 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