使用snakeyaml(Java)和YamlDotNet(C#)

时间:2015-09-23 13:32:34

标签: snakeyaml yamldotnet

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

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

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

1 个答案:

答案 0 :(得分: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());

See a fully working fiddle here