Skip to main content

[json-processing-spec users] Re: BigDecimal for equals()/hashCode()

  • From: Jitendra Kotamraju < >
  • To:
  • Cc: Joe Darcy < >
  • Subject: [json-processing-spec users] Re: BigDecimal for equals()/hashCode()
  • Date: Mon, 28 Jan 2013 17:12:47 -0800

* I think the conversions are loose here. For example, how do we convert String to double. or, you
specify  "Returns the {@code double} value nearest to this JSON number." IMO, that's not good enough.

It is better to define the exact semantics using existing JDK classes, for e.g using BigDecimal and its associated methods.
An implementation doesn't have to use BigDecimal but it must follow the semantics. Hence, in the current javadoc,
we specify "a BigDecimal *may be* used internally".  All other methods could be defined on top of getBigDecimalValue() method.
So two step process. 1. How getBigDecimalValue() returns correct BigDecimal from various input types 2. Use getBigDecimalValue()
for other methods. If that's not clear, we should expand the javadoc to say that any other means can be used to achieve the
defined semantics.

* Regarding equals()/hashCode(), if we don't want scale to be in consideration, then we should say it is based on
getBigDecimalValue().stripTrailingZeros(). A *naive* impl would be

     public int hashCode() {
-        return getBigDecimalValue().hashCode();
+      return getBigDecimalValue().stripTrailingZeros().hashCode();
     }
 
     public boolean equals() {
         ...
         JsonNumber other = (JsonNumber)obj;
-        return getBigDecimalValue().equals(other.getBigDecimalValue());
+       return getBigDecimalValue().stripTrailingZeros().equals(other.getBigDecimalValue().stripTrailingZeros());
     }

see inline

On 01/28/2013 02:24 PM, Jonathan Fuerth wrote:
" type="cite">
Okay, here's what I arrived at over the weekend:

Thanks for working on this !

" type="cite">
1. Remove "get" from the names of the getXXXValue() and getXXXValueExact() methods. This matches the naming scheme used in java.lang.Number. I know we've decided JsonNumber should not implement java.lang.Number, but the "getless" naming style seems more up-to-date to me. I guess we've come full-circle on naming conventions! :)
We shouldn't limit this change to one class. Either we should change all over the API or none.
" type="cite">

2. Remove the NumberType enum. I believe it originally served more of a purpose ambitious, but in its current form with only two members, it's much more cumbersome to use than, say, a JsonNumber.isIntegral() method.
That may be true.

" type="cite">

3. Following from 2, should we add fitsInt(), fitsLong(), fitsBigInteger(), and fitsDouble() methods? Without them, it is hard for application code to test if the XXXValueExact() methods will throw an exception.
That was the original intention of the enum. It is kind of difficult to implement fitsDouble(), hence we provided one constant for whole decimal values.
" type="cite">

4. The test case JsonNumberTest.testLeadingZeroes() doesn't appear to do what its name implies. My understanding is that leading zeroes are not permitted by the JSON spec, so we should rewrite the test to feed in a number with leading zeroes and verify an exception is thrown.
I agree

Jitu
" type="cite">

-Jonathan

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.

Although JSON originated from _javascript_, I think its increasingly common that json is also used for integration between other platforms than webserver/browser.
We had that discussion. For e.g http://java.net/projects/json-processing-spec/lists/users/archive/2012-10/message/48
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.

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.

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 anybody.

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 source.

And finally I think a specification can also intentially leave things undefined or implementation defined when it allows performance or space advantages.

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"))

implementation defined return value

parse("10.0") ~ build(10.0)
build(10.0) ~ build((int)10)
build(new BigDecimal("10.0")) ~ build(10.0)

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.

Jörn







[json-processing-spec users] BigDecimal for equals()/hashCode()

Jitendra Kotamraju 01/24/2013

[json-processing-spec users] Re: BigDecimal for equals()/hashCode()

Jonathan Fuerth 01/24/2013

[json-processing-spec users] Re: BigDecimal for equals()/hashCode()

Jitendra Kotamraju 01/24/2013

[json-processing-spec users] Re: BigDecimal for equals()/hashCode()

Jonathan Fuerth 01/25/2013

[json-processing-spec users] Re: BigDecimal for equals()/hashCode()

Jonathan Fuerth 01/25/2013

[json-processing-spec users] Re: BigDecimal for equals()/hashCode()

Jörn Horstmann 01/24/2013

[json-processing-spec users] Re: BigDecimal for equals()/hashCode()

Jitendra Kotamraju 01/24/2013

[json-processing-spec users] Re: BigDecimal for equals()/hashCode()

Jonathan Fuerth 01/25/2013

[json-processing-spec users] Re: BigDecimal for equals()/hashCode()

Jonathan Fuerth 01/28/2013

[json-processing-spec users] Re: BigDecimal for equals()/hashCode()

Jonathan Fuerth 01/28/2013

[json-processing-spec users] Re: BigDecimal for equals()/hashCode()

Jitendra Kotamraju 01/29/2013

[json-processing-spec users] Re: BigDecimal for equals()/hashCode()

Jonathan Fuerth 01/29/2013

[json-processing-spec users] Re: BigDecimal for equals()/hashCode()

Jitendra Kotamraju 01/29/2013

[json-processing-spec users] Re: BigDecimal for equals()/hashCode()

Jonathan Fuerth 01/29/2013
 
 
Close
loading
Please Confirm
Close