Skip to content

[json-org] fix issue with parsing big numbers #32

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

Merged
merged 1 commit into from
Apr 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public JSONArray deserialize(JsonParser p, DeserializationContext ctxt)
array.put(p.getNumberValue());
continue;
case VALUE_NUMBER_FLOAT:
array.put(p.getNumberValue());
array.put(p.getDecimalValue());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only now realizing that this is actually behavioral change too. Hmmh.
So even if improvement, might break code if the exposed number changes from Double to BigDecimal?
Or maybe JSONP API encapsulates so this is not the case?

Since I already merged changes for JSR-353/JSONP will merge this too, just noting that we may get bug reports for 2.15.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pjfanning Doh. Not JSONP/JSR-353. Still, similar concerns.

But quick question: would it make sense to instead call p.getNumberValueExact()? This would at least retain exact Float/Double for binary formats? Would change it to BigDecimal for JSON and other textual formats, which is probably good overall.
WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if p.getNumberValueExact() works, then I'd be happy with that change - let me try a PR with that instead

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

b.add(name, p.getNumberValueExact()); doesn't compile
ie b.add does not support Number

I looked at the code in the json libs and they tend to use BigDecimal under the hood - so I think the risks of the jackson changes are low.

I think it is better to take the risk that someone will report an edge case than to add complicated logic using p.getNumberValueExact() and then lots of instanceof checks with casts.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh. Yes, I forgot the challenge wrt non-typed Number. I concur with your assessment.
Ideally we'd have more time for testing but TBH this module probably won't get all that much beta-testing compared to jackson-databind or jackson-core.

continue;
case VALUE_EMBEDDED_OBJECT:
array.put(p.getEmbeddedObject());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public JSONObject deserialize(JsonParser p, DeserializationContext ctxt)
ob.put(fieldName, p.getNumberValue());
continue;
case VALUE_NUMBER_FLOAT:
ob.put(fieldName, p.getNumberValue());
ob.put(fieldName, p.getDecimalValue());
continue;
case VALUE_EMBEDDED_OBJECT:
ob.put(fieldName, p.getEmbeddedObject());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import org.json.*;

import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
import java.math.BigDecimal;

public class SimpleReadTest extends ModuleTestBase
{
Expand Down Expand Up @@ -46,4 +46,23 @@ public void testReadArray() throws Exception
JSONArray array2 = array.getJSONArray(6);
assertEquals(0, array2.length());
}

public void testBigInteger() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JsonOrgModule());

JSONObject val = mapper.readValue("{\"val\":2e308}", JSONObject.class);
assertEquals(new BigDecimal("2e308").toBigInteger(), val.getBigInteger("val"));
}

public void testBigIntegerArray() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JsonOrgModule());

JSONArray array = mapper.readValue("[2e308]", JSONArray.class);
assertEquals(1, array.length());
assertEquals(new BigDecimal("2e308").toBigInteger(), array.getBigInteger(0));
}
}