使用 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());
我正在使用 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());