我正在使用YAML在C#GUI和服务器端Java之间进行通信,这在一般情况下运行良好。但是,如果我传递一个Double的字段,并且Java端的值为Double.NaN,则Yaml传递为“.NaN”,当我在C#端反序列化时,会抛出'System.FormatException'作为C#期望字符串“NaN”[不是“.NaN”]。
有没有人知道是否有办法拦截反序列化器,或者添加格式化以便在C#端“.NaN”可以解析为双倍?
(我能想到的一个解决方法是在将所有NaN更改为特殊值之前将其更改为YAML,然后在C#中识别特殊值并转换回NaN,但这似乎是一个大黑客。)
答案 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());