-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
Summary
The JsonNumber.of(double) factory method has a bug where it hardcodes decimalOffset=0 and exponentOffset=0 when creating the JsonNumberImpl. This causes toLong() to fail for integral doubles like 123.0.
Root Cause
In JsonNumber.java line 117:
static JsonNumber of(double num) {
if (!Double.isFinite(num)) {
throw new IllegalArgumentException("Not a valid JSON number");
}
var str = Double.toString(num);
return new JsonNumberImpl(str.toCharArray(), 0, str.length(), 0, 0);
// ^^^^^ BUG: hardcoded offsets
}For Double.toString(123.0) which returns "123.0":
decimalOffsetshould be3(position of.) but is passed as0- This causes
initNumLong()inJsonNumberImplto misparse the number
Reproduction
var jn = JsonNumber.of(123.0);
jn.toString(); // "123.0" - OK
jn.toDouble(); // 123.0 - OK
jn.toLong(); // THROWS: "123.0 cannot be represented as a long"
// EXPECTED: 123L (per API docs, "123.0" should be convertible)Comparison with Json.parse()
var parsed = Json.parse("123.0");
parsed.toLong(); // 123L - WORKS correctlyThe difference is that Json.parse() correctly computes the decimalOffset during parsing.
Suggested Fix
Option 1 - Reuse JsonNumber.of(String) which delegates to parser:
static JsonNumber of(double num) {
if (!Double.isFinite(num)) {
throw new IllegalArgumentException("Not a valid JSON number");
}
return JsonNumber.of(Double.toString(num));
}Option 2 - Compute correct offsets:
static JsonNumber of(double num) {
if (!Double.isFinite(num)) {
throw new IllegalArgumentException("Not a valid JSON number");
}
var str = Double.toString(num);
var chars = str.toCharArray();
int dec = str.indexOf('.');
int exp = str.indexOf('e');
if (exp == -1) exp = str.indexOf('E');
return new JsonNumberImpl(chars, 0, chars.length,
dec == -1 ? -1 : dec,
exp == -1 ? -1 : exp);
}This is an Upstream Bug
This bug exists in OpenJDK jdk-sandbox json branch at commit 91a479d. The upstream tests in TestJsonNumber.java do not cover this case - they test of(double).toDouble() but never of(double).toLong() for integral doubles.
Affected Versions
- jdk-sandbox json branch (upstream)
- java.util.json.Java21 backport 0.1.9 (this repo, synced from upstream)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels