http://gwt-code-reviews.appspot.com/1601805/diff/11002/user/src/com/google/web/bindery/autobean/shared/ValueCodex.java
File user/src/com/google/web/bindery/autobean/shared/ValueCodex.java
(right):
http://gwt-code-reviews.appspot.com/1601805/diff/11002/user/src/com/google/web/bindery/autobean/shared/ValueCodex.java#newcode41
user/src/com/google/web/bindery/autobean/shared/ValueCodex.java:41: if
(value.isNumber()) {
On 2012/04/11 15:57:02, skybrian wrote:
Although strictly speaking this is an improvement, I think users will
be
confused by a partial implementation. If we support converting JSON
numbers to
BigDecimals at all, as a naive user I'd expect to be able to handle
BigDecimal's
entire range, and not be limited to a JavaScript number's range due to
an
internal limitation. (If a smaller range is okay, I wouldn't be using
a
BigDecimal in the first place.)
This is the same rationale as for accepting numbers in JSON for longs
(though in that case it used to work and then there was a change that
broke it).
It seems like we should be able to do better than this by accessing
the
underlying string without converting it to a number first, so we can
handle
BigDecimal's entire range instead of just the JavaScript range for a
number?
But I tried drilling down and I'm not following how JSON parsing
works.
isNumber() is not "converting to number".
Here's how things work in AutoBeans:
1. received JSON data is parsed into a Splittable. This will use
JsonUtils.safeEval on GWT-client side (will use the browser's native
JSON.parse if available, and fallback to eval() with some regexp sanity
checks), returning a JsoSplittable implementation (i.e. a JS object
equivalent to the serialized JSON), and org.json in a plain VM,
returning a JsonSplittable implementation (i.e. backed by a JSONObject).
When encountering numbers in the JSON, the JsonSplittable calls
doubleValue() on them; in web mode though, numbers in the JSON have to
be parsable into JS numbers, or JSON.parse will throw.
2. then Splittable is wrapped by AutoBeanCodex into an AutoBean. Note
that you can also get a Splittable out of an AutoBean, or manually
constructing it, so a Splittable does not necessarily comes from a
serialized JSON message (though most of the time that'll be the case)
3. when accessing a property of the AutoBean, the value is read out of
the Splittable (as another Splittable) and "reified" (and cached in a
Map within the AutoBean): using AutoBeanCodex for other autobeans, or
ValueCodex to decode value-type properties (this is where we are here)
So, if you receive the following JSON:
{"foo": 123}
the Splittable for 123 (returned by get("foo") on the Splittable for the
object) will return true for isNumber() and false for isString(); and it
will return the double 123.0 for asNumber() and 'null' for asString().
If you receive the following:
{"foo": "123"}
then the Splittable for "123" will return false for isNumber() and true
for isString(); and will possibly throw or return null for asNumber(),
and return the string "123" for asString().
There's no parsing or conversion involved at that time, these are
mutually exclusive states.
BigDecimal, BigInteger and Long all possibly overflowing a JS number and
always encoded as strings.
This was not the case in an earlier version of GWT, so you could only
send values that fitted into a JS Number, i.e. java.lang.Double; and
that was the breaking change when BobV fixed this to serialize to
strings, but no longer accepting numerics as input.
Here, we're applying Postel's law of accepting both {"foo":123} and
{"foo":"123"} for those "big numbers".
Now imagine I used a Double, and find out I need a larger range (or
better precision), so I switch to a BigDecimal.
Without this CL, I can no longer parse a {"foo":123} JSON (or actually,
it'll give me a 'null' value for "foo" instead of a BigDecimal with
value 123), and that JSON could have been saved in localStorage...
I added the lenient parsing behavior to BigDecimal/BigInteger only for
consistency with Long though, so I'm OK removing it if you prefer (Long
had a breaking change at some point, but not BigInteger/BigDecimal)
http://gwt-code-reviews.appspot.com/1601805/
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors