[json-processing-spec users] Re: BigDecimal for equals()/hashCode()
- From: Jonathan Fuerth <
- Cc: Joe Darcy <
- Subject: [json-processing-spec users] Re: BigDecimal for equals()/hashCode()
- Date: Thu, 24 Jan 2013 21:18:53 -0500
On 2013-01-24, at 4:55 PM, Jitendra Kotamraju wrote:
> ccing joe also.
> On 01/24/2013 01:11 PM, Jörn Horstmann wrote:
>> Thanks Jonathan, thats a nice summary of the issues regarding JsonNumber.
>> that json is also used for integration between other platforms than
> We had that discussion. For e.g
Yes, absolutely. I attempted to address that in the previous post, as well as
the thread that came before it.
The point I was making is different: if you choose to include numbers that
are not exactly representable as double in a JSON message, you are
& commandline tools, etc.) from processing that message.
Put another way, if you have 20 steps in a process, and just one of them is
>> Also for other languages that include a more complete numeric tower. I
>> haven't come across an example where numeric strings are used to preserve
>> precision, this might be fine if the value is just used for display
>> purposes in a browser, but for a data exchange format the number syntax
>> should be preferred.
For the reasons outlined here and in my previous messages, I disagree on that
Where I do agree is that JSR353 must specify that JsonNumber always preserves
numbers with the full precision it has been given. End users can decide if it
is wise to take advantage of that behaviour or not.
>> As api or library providers we should try to keep the most precision
>> possible for a number and let the library user decide how it is treated.
>> This can be done by either storing the number as a BigDecimal or String
>> internally. If we allow both storage options the contract for equals and
>> hashCode would have to be based on
> Two storage options would be difficult to define the semantics in all cases.
We only have to define the semantics in the spec. As long as the semantics
are sound from a user's point of view, only implementers of the spec have to
deal with the consequences. :-)
>> their string representation, as the hashCode calculation for BigDecimal is
>> not exactly specified.
>> (Consistent equals and hashCode behaviour is the main reason that I would
>> prefer JsonBuilder and related classes to be interfaces, so an
>> implementation could use the same classes for numbers created from builder
>> and reader usage.)
> If we don't define equals and hashCode, then objects from provider 1 will
> not work with objects of provider 2. I don't know if that's a problem for
That's a good question. It's within our means to force the issue in the
equals() and hashCode() specifications. I'm not sure if it's worthwhile to do
so... it would only be really useful if every JsonValue was comparable across
implementations. I think it might be more trouble than it's worth.
>> I hope that most java developers dealing with monetary values are using
>> BigDecimal, and so should be familiar with its behavior of equals. I also
>> think that equal checks are mostly done between objects from the same
I agree on both points. But this still doesn't mean that the common use case
for JsonNumber requires BigDecimal semantics.
>> And finally I think a specification can also intentially leave things
>> undefined or implementation defined when it allows performance or space
That's the core issue I'm driving at (let the implementation decide), but I
agree with Jitu that we have to specify *something*. :-)
But maybe there's something to it after all. The one question we've never
asked is, "who ever compares JsonNumber instances for equality, anyway?"
What's the use case here?
>> So in pseudocode, ~ meaning equals, build being a shortcut for JsonBuilder
>> and parse for JsonReader:
>> equals returns true:
>> parse("10.0") ~ parse("10.0")
>> build(10.0) ~ build(10.0)
>> build(new BigDecimal("10.0")) ~ build(new BigDecimal("10.0"))
>> equals returns false
>> parse("10.0") ~ parse("10")
>> build(new BigDecimal("10.0")) ~ build(new BigDecimal("10"))
Hmm, here's where I differ. I'm suggesting that these should return different
values from toString() ("10.0" vs. "10") but they should compare equal and
share the same hash code.
>> implementation defined return value
>> parse("10.0") ~ build(10.0)
>> build(10.0) ~ build((int)10)
>> build(new BigDecimal("10.0")) ~ build(10.0)
Agreed, these are difficult cases. I'm inclined to take an "all or nothing"
approach on numeric equality. So I'd still prefer to specify these are all
>> This might be controversial at first but its alway possible to tighten the
>> rules in a maintenance release, while its not possible to loosen the
>> definitions due to backwards compatibility.