jsonp-api
jsonp-api copied to clipboard
provide "NaN" and "Infinity" when (de)serializing Java Numbers
Json-P uses this to (de)serialize Double-values to and from Json:
JsonGenerator write(double value);
Please provide the ability to (de)serialize "NaN", "+Infinity" and "-Infinity" with any type of Numbers (Double, etc) to produce and consume something like this
{
"val1" : "NaN",
"val2" : 1.0,
"val3" : 0.0,
"val4" : "+Infinity"
"val5" : "-Infinity"
}
converter to produce json string:
try{
// normal conversion to double
}
catch(NumberFormatException ex){
if(Double.isNaN(val)) return "NaN";
if(Double.isInfinite(val) && val>0) return "Infinity";
if(Double.isInfinite(val) && val<0) return "-Infinity";
}
converter to consume "NaN" and "Infinity" from Json-String:
try{
if(val == "NaN") return Double.NaN;
if(val == "Infinity") return Double.POSITIVE_INFINITY;
if(val == "-Infinity") return Double.NEGATIVE_INFINITY;
// normal conversion to double
...
}
For example, Json-P could automatically use the Double-(de)serializer, if Double-Objects are used. If Json-P detects primitive double-types, the double-(de)serializer can be used.
Also, Json-P should provide the Json-P configuration property NAN_AS_STRINGS:
// uses strings for "NaN", "+Infinity", "-Infinity"
// instead of throwing NumberFormatException when (de)serializing
Maps.of(JsonGenerator.WRITE_NAN_AS_STRINGS, true)
Actually, Json-P are not able to consume and produce Java Numbers complete: "NaN" and "Infinity" are still valid information about numbers which should not be thrown with exceptions by default.
Related:
- https://github.com/eclipse-ee4j/jsonp/issues/160
- https://github.com/eclipse-ee4j/yasson/issues/306
Copying a bit of context over from #160, @leadpony made an important comment here: https://github.com/eclipse-ee4j/jsonp/issues/160#issuecomment-521802692
Which states:
The JSON grammar does not allow NaN and Infinity to be represented and this change may produce JSON which is not interchangeable between various kinds of platforms.
RFC 8259 states:
Numeric values that cannot be represented in the grammar below (such as Infinity and NaN) are not permitted.
The feature can be configured with an option WRITE_NAN_AS_STRINGS in Jackson.
Suggestion:
Provide 3 states when dealing with Java Numbers:
1. Config with WRITE_NAN_AS_STRINGS
// uses strings for "NaN", "+Infinity", "-Infinity"
// instead of throwing NumberFormatException when (de)serializing
Maps.of(JsonGenerator.WRITE_NAN_AS_STRINGS, true);
produces/consumes:
{
"val1" : "NaN",
"val2" : 1.0,
"val3" : 0.0,
"val4" : "+Infinity"
"val5" : "-Infinity"
}
2. Config with WRITE_NAN_AS_NULLS
// uses NULL for "NaN", "+Infinity", "-Infinity"
// instead of throwing NumberFormatException when (de)serializing
Maps.of(JsonGenerator.WRITE_NAN_AS_NULLS, true);
produces/consumes:
{
"val1" : null,
"val2" : 1.0,
"val3" : 0.0,
"val4" : null
"val5" : null
}
3. If both are true
// uses "NaN", "+Infinity", "-Infinity"-Strings for Number Wrapper types (Double,..)
// uses NULL for primitive types (double,..)
// instead of throwing NumberFormatException when (de)serializing
Maps.of(
JsonGenerator.WRITE_NAN_AS_STRINGS, true,
JsonGenerator.WRITE_NAN_AS_NULLS, true);
3. If both settings are false throws NumberFormatException when (de)serializing "NaN", "+Infinity", "-Infinity".
To sum up:
The default should be at least JsonGenerator.WRITE_NAN_AS_NULLS, true (RFC-compliant) instead of throwing exception. The default with Number Wrapper types could be JsonGenerator.WRITE_NAN_AS_STRINGS, true.
I am implementing this in Parsson.
In the point 3 I have a question. When both are true, the logic is split in 2 ways:
// uses "NaN", "+Infinity", "-Infinity"-Strings for Number Wrapper types (Double,..)
// uses NULL for primitive types (double,..)
The first one 'uses "NaN", "+Infinity", "-Infinity"-Strings for Number Wrapper types (Double,..)' over complicates the logic a lot, because internally it works with primitive types.
Recently a new method was added in JsonValue to manage Numbers here https://github.com/eclipse-ee4j/jsonp/pull/302 but by default it delegates in existing methods that works primitive types.
What is the motivation to make a split between primitive and not primitive types when both are true?
- [ ] TCK