Conversation
6348091 to
38b639d
Compare
Convert each integer type to a BigInteger to validate that the value is within the proper range, otherwise throw a NumberFormatException. Added corresponding tests to JsonParserTest.
38b639d to
bedcb10
Compare
|
Your changes look good, thanks! Could you please:
One issue with this approach might be lossless conversion from floating point values. Because your code uses Sorry for this long comment; I hope some of the points are helpful though. Also as side note: GitHub understands certain keywords. Could you please edit the description of your pull request and add the following, so GitHub understands that this pull request closes that issue:
Note that I am not a member of this project. Feel free to consider my comment only as suggestion. |
374354c to
7c58d0a
Compare
eamonnmcmanus
left a comment
There was a problem hiding this comment.
Thanks for taking this on!
Though this is potentially a breaking change, it seems like the right thing to do, both because it fixes potential silent data loss and because it is consistent with what we do elsewhere (as detailed in the issue).
The new tests are great, but I had a few suggestions for the implementation changes.
| public long getAsLong() { | ||
|
|
||
| if (isNumber()) { | ||
| final BigInteger val = getAsBigInteger(); |
There was a problem hiding this comment.
This is suddenly very expensive if value is already a Long. getAsBigInteger() will convert it to a string which it will then parse back into a new BigInteger object. If this method is called more than once, it will do the same thing every time. I think it would be worth adding instanceof checks to bypass this for when value is Long or any of the smaller java.lang types, and likewise in the other cases. Also, you're checking isNumber() here, so it looks as if you could reasonably move the true-case from the isNumber() ? code below.
Also we can borrow an idea from the implementation of BigInteger.longValueExact() for a simpler overflow check. (Since that method was added in Java 8 we unfortunately can't use it directly.)
I'm imagining code something like this:
if (isNumber()) {
if (value instanceof Long || value instanceof Integer || value instanceof Short || value instanceof Byte) {
return ((Number) value).longValue();
}
BigInteger val = getAsBigInteger();
if (val.bitLength() >= 64) {...throw...}
return val.longValue();
}
return Long.parseLong(getAsString());|
|
||
| try { | ||
| jsonObject.get("bigIntegerU").getAsLong(); | ||
| fail("Big Integer values greater than Long.MAX_VALUE should not parse as a Long"); |
There was a problem hiding this comment.
I would prefer to write BigInteger here with no space.
| } | ||
|
|
||
| /** | ||
| * convenience method to get this element as a primitive byte. |
There was a problem hiding this comment.
These methods can all throw NumberFormatException, even before this change. I think it is the javadoc of the overridden methods in JsonElement that should be updated to reflect that.
|
I've run this change against Google's internal tests and unfortunately there were quite a few failures. It looks as if there might be about 10 distinct root causes, which fall into two main categories:
Although we could imagine tweaks to allow these cases to continue to work, or perhaps to update the tests so they don't trigger the problems, my feeling is that it is probably best to leave well enough alone. So I am probably going to close this PR and the associated issue. |
|
Sounds good @eamonnmcmanus and @Marcono1234! We greatly appreciate your feedback. Clearly, building in the necessary checks to make all possible test cases resolve as expected is a bit more laborious and expensive than at first glance from the initial issue posting. |
Just curious, are those tests running directly against the |
Uh oh!
There was an error while loading. Please reload this page.