1

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

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

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

4

1 回答 1

0

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

在这里看到一个完整的小提琴

于 2015-09-24T12:56:00.317 回答