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

Jackson changes additional values to infinite in case of special JSON structures and existing infinite values #1397

Closed
Rodenstock opened this issue Feb 4, 2025 · 9 comments
Milestone

Comments

@Rodenstock
Copy link

Rodenstock commented Feb 4, 2025

With infinite values of float types and the following JSON structure, Jackson unexpectedly changes additional values since version 2.18.0.
Radius is originally set to infinity (1.7976931348623157e+308). After selecting the value as JSONB from a PostgreSQL database and serializing it to JSON, the value of center.x is also set to infinity (1.7976931348623157e+308).

All versions greater than or equal to 2.18.0 are affected.
The last working version is 2.17.3.

{
  "results": [
    {
      "radius": 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,
     "type": "center",
      "center": {
        "x": -11.0,
        "y": -2.0
      }
    }
  ]
}

Jackson serializes the JSON-Object into the following JSON:

{
  "results": [
    {
      "radius": 1.7976931348623157e+308,
     "type": "center",
      "center": {
        "x": 1.7976931348623157e+308,
        "y": -2.0
      }
    }
  ]
}

Below is the code for reproducing the issue.

package org.example;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.util.Arrays;

class Point {
    private Double x;
    private Double y;

    public Double getX() {
        return x;
    }

    public void setX(Double x) {
        this.x = x;
    }

    public Double getY() {
        return y;
    }

    public void setY(Double y) {
        this.y = y;
    }
}

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.EXISTING_PROPERTY,
        property = "type",
        visible = true)
@JsonSubTypes(@JsonSubTypes.Type(value = CenterResult.class, name = "center"))
abstract class Result {
    private String type;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

class CenterResult extends Result {
    private Point center;

    private Double radius;

    public Double getRadius() {
        return radius;
    }

    public void setRadius(Double radius) {
        this.radius = radius;
    }

    public Point getCenter() {
        return center;
    }

    public void setCenter(Point center) {
        this.center = center;
    }
}

class Root {
    private Result[] results;

    public Result[] getResults() {
        return results;
    }

    public void setResults(Result[] results) {
        this.results = results;
    }
}

public class Main {
    public static void main(String[] args) throws IOException {
        var dataString = """
            {
              "results": [
                {
                  "radius": 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,
                 "type": "center",
                  "center": {
                    "x": -11.0,
                    "y": -2.0
                  }
                }
              ]
            }
        """;

        var object = new ObjectMapper().readValue(dataString, Root.class);

        var result = (CenterResult) Arrays.stream(object.getResults()).findFirst().orElseThrow();

        System.out.println(result.getCenter().getX()); // prints 1.7976931348623157E308 instead of -11.0
    }
}
@pjfanning
Copy link
Member

This seems like #1391 to me. A bug that added in 2.15.0. Hopefully, there will be releases soon to address this. Could you try 2.18.3-SNAPSHOT?

https://oss.sonatype.org/content/repositories/snapshots/com/fasterxml/jackson/core/jackson-core/2.18.3-SNAPSHOT/

@Rodenstock
Copy link
Author

Thank you very much for this information.

The problem also occurs with 2.18.3-SNAPSHOT, but seems to be fixed in 2.19.0-SNAPSHOT.

pjfanning added a commit to FasterXML/jackson-databind that referenced this issue Feb 4, 2025
@pjfanning
Copy link
Member

Thanks @Rodenstock - it does look like the parts of the 2.19 fix that we backported and thought were enough - that these may not be enough and that we may need to backport the full 2.19 change.

@cowtowncoder
Copy link
Member

@pjfanning makes sense given that 2.19 fully clears _numberString on reset() calls, whereas 2.18 patch was minimal, addressing specific call sequence (to reduce likelihood of regressions).

But the question then is whether more tweaking helps, or should we just backport full 2.19 fix.

@pjfanning
Copy link
Member

pjfanning commented Feb 4, 2025

@pjfanning makes sense given that 2.19 fully clears _numberString on reset() calls, whereas 2.18 patch was minimal, addressing specific call sequence (to reduce likelihood of regressions).

But the question then is whether more tweaking helps, or should we just backport full 2.19 fix.

Is there anything else to backport after #1400 ?

@cowtowncoder
Copy link
Member

Is there anything else to backport after #1400 ?

I don't think so.

@pjfanning
Copy link
Member

I can't guarantee that there are no more edge cases but #1400 fixes this latest issue. This seems to differ from the original case because instead of a normal int, the first number here is a very long int (big int). So far, there is no evidence of numbers with decimal points leaking into following numbers.

@cowtowncoder
Copy link
Member

Without this fix, I think BigDecimal could leak. But with fix I am not aware of any mechanism.

cowtowncoder added a commit that referenced this issue Feb 5, 2025
@cowtowncoder cowtowncoder added this to the 2.18.3 milestone Feb 5, 2025
@cowtowncoder
Copy link
Member

Fix merged: will be in

  • 2.19.0
  • 2.18.3
  • 2.17.4 (if it is released), or possibly 2.17.4.1 (micro-patch, otherwise)

cowtowncoder pushed a commit to FasterXML/jackson-databind that referenced this issue Feb 5, 2025
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