Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provide "NaN" and "Infinity" when (de)serializing Java Numbers #209

Open
nimo23 opened this issue Aug 16, 2019 · 4 comments
Open

provide "NaN" and "Infinity" when (de)serializing Java Numbers #209

nimo23 opened this issue Aug 16, 2019 · 4 comments

Comments

@nimo23
Copy link

nimo23 commented Aug 16, 2019

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:

@aguibert
Copy link

Copying a bit of context over from #160, @leadpony made an important comment here: #160 (comment)

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.

@nimo23
Copy link
Author

nimo23 commented Aug 16, 2019

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.

@jbescos
Copy link
Member

jbescos commented Sep 23, 2021

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 #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?

@jbescos
Copy link
Member

jbescos commented Oct 6, 2021

  • TCK

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants