I'm using YAML to communicate between C# GUI and server side Java, which is working fine in general. However, if I pass a field that is a Double and the value is Double.NaN on Java side the Yaml passes as ".NaN", and when I come to deserialize on the C# side a 'System.FormatException' is thrown as C# expects the string "NaN" [not ".NaN"].
Does anyone know if there is a way to intercept the deserializer, or add formatting so that on the C# side ".NaN" can be parsed in a double?
(One workaround I can think of is changing all NaN's to a special value before serliazing to YAML, and then on C# recognizing the special value and converting back to NaN, but this seems like a big hack.)
It seems that this is a bug in the way YamlDotNet handles floats. Until it is fixed, you can work around it by registering a custom node INodeDeserializer
that will handle these special cases.
Here is a quick-and-dirty implementation of such a deserializer:
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;
}
}
The way to register it is:
var deserializer = new Deserializer();
deserializer.NodeDeserializers.Insert(0, new FloatNodeDeserializer());