Skip to content

Commit 59761f6

Browse files
authored
Merge pull request #58 from johnjaylward/SimplifyNumberWrap
Adds tests for numbers
2 parents c400de3 + 0b1dbe9 commit 59761f6

File tree

4 files changed

+339
-2
lines changed

4 files changed

+339
-2
lines changed
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
package org.json.junit;
2+
3+
import java.math.BigDecimal;
4+
import java.math.BigInteger;
5+
import java.math.RoundingMode;
6+
7+
/**
8+
* basic fraction class, no frills.
9+
* @author John Aylward
10+
*
11+
*/
12+
public class Fraction extends Number implements Comparable<Fraction> {
13+
/**
14+
* serial id.
15+
*/
16+
private static final long serialVersionUID = 1L;
17+
18+
/**
19+
* value as a big decimal.
20+
*/
21+
private final BigDecimal bigDecimal;
22+
23+
/**
24+
* value of the denominator.
25+
*/
26+
private final BigInteger denominator;
27+
/**
28+
* value of the numerator.
29+
*/
30+
private final BigInteger numerator;
31+
32+
/**
33+
* @param numerator
34+
* numerator
35+
* @param denominator
36+
* denominator
37+
*/
38+
public Fraction(final BigInteger numerator, final BigInteger denominator) {
39+
super();
40+
if (numerator == null || denominator == null) {
41+
throw new IllegalArgumentException("All values must be non-null");
42+
}
43+
if (denominator.compareTo(BigInteger.ZERO)==0) {
44+
throw new IllegalArgumentException("Divide by zero");
45+
}
46+
47+
final BigInteger n;
48+
final BigInteger d;
49+
// normalize fraction
50+
if (denominator.signum()<0) {
51+
n = numerator.negate();
52+
d = denominator.negate();
53+
} else {
54+
n = numerator;
55+
d = denominator;
56+
}
57+
this.numerator = n;
58+
this.denominator = d;
59+
if (n.compareTo(BigInteger.ZERO)==0) {
60+
this.bigDecimal = BigDecimal.ZERO;
61+
} else if (n.compareTo(d)==0) {// i.e. 4/4, 10/10
62+
this.bigDecimal = BigDecimal.ONE;
63+
} else {
64+
this.bigDecimal = new BigDecimal(this.numerator).divide(new BigDecimal(this.denominator),
65+
RoundingMode.HALF_EVEN);
66+
}
67+
}
68+
69+
/**
70+
* @param numerator
71+
* numerator
72+
* @param denominator
73+
* denominator
74+
*/
75+
public Fraction(final long numerator, final long denominator) {
76+
this(BigInteger.valueOf(numerator),BigInteger.valueOf(denominator));
77+
}
78+
79+
/**
80+
* @return the decimal
81+
*/
82+
public BigDecimal bigDecimalValue() {
83+
return this.bigDecimal;
84+
}
85+
86+
@Override
87+
public int compareTo(final Fraction o) {
88+
// .equals call this, so no .equals compare allowed
89+
90+
// if they are the same reference, just return equals
91+
if (this == o) {
92+
return 0;
93+
}
94+
95+
// if my denominators are already equal, just compare the numerators
96+
if (this.denominator.compareTo(o.denominator)==0) {
97+
return this.numerator.compareTo(o.numerator);
98+
}
99+
100+
// get numerators of common denominators
101+
// a x ay xb
102+
// --- --- = ---- ----
103+
// b y by yb
104+
final BigInteger thisN = this.numerator.multiply(o.denominator);
105+
final BigInteger otherN = o.numerator.multiply(this.denominator);
106+
107+
return thisN.compareTo(otherN);
108+
}
109+
110+
@Override
111+
public double doubleValue() {
112+
return this.bigDecimal.doubleValue();
113+
}
114+
115+
/**
116+
* @see java.lang.Object#equals(java.lang.Object)
117+
*/
118+
@Override
119+
public boolean equals(final Object obj) {
120+
if (this == obj) {
121+
return true;
122+
}
123+
if (obj == null) {
124+
return false;
125+
}
126+
if (this.getClass() != obj.getClass()) {
127+
return false;
128+
}
129+
final Fraction other = (Fraction) obj;
130+
return this.compareTo(other) == 0;
131+
}
132+
133+
@Override
134+
public float floatValue() {
135+
return this.bigDecimal.floatValue();
136+
}
137+
138+
/**
139+
* @return the denominator
140+
*/
141+
public BigInteger getDenominator() {
142+
return this.denominator;
143+
}
144+
145+
/**
146+
* @return the numerator
147+
*/
148+
public BigInteger getNumerator() {
149+
return this.numerator;
150+
}
151+
152+
/**
153+
* @see java.lang.Object#hashCode()
154+
*/
155+
@Override
156+
public int hashCode() {
157+
final int prime = 31;
158+
int result = 1;
159+
result = prime * result + (this.bigDecimal == null ? 0 : this.bigDecimal.hashCode());
160+
return result;
161+
}
162+
163+
@Override
164+
public int intValue() {
165+
return this.bigDecimal.intValue();
166+
}
167+
168+
@Override
169+
public long longValue() {
170+
return this.bigDecimal.longValue();
171+
}
172+
173+
/**
174+
* @see java.lang.Object#toString()
175+
*/
176+
@Override
177+
public String toString() {
178+
return this.numerator + "/" + this.denominator;
179+
}
180+
}

src/test/java/org/json/junit/JSONObjectTest.java

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package org.json.junit;
22

3+
import static org.junit.Assert.assertEquals;
34
import static org.junit.Assert.assertFalse;
45
import static org.junit.Assert.assertNull;
56
import static org.junit.Assert.assertTrue;
6-
import static org.junit.Assert.assertEquals;
77
import static org.mockito.Mockito.mock;
88
import static org.mockito.Mockito.when;
99

@@ -20,6 +20,7 @@
2020
import java.util.List;
2121
import java.util.Locale;
2222
import java.util.Map;
23+
import java.util.concurrent.atomic.AtomicInteger;
2324

2425
import org.json.CDL;
2526
import org.json.JSONArray;
@@ -49,7 +50,7 @@ public void jsonObjectByNullBean() {
4950
MyBean myBean = null;
5051
new JSONObject(myBean);
5152
}
52-
53+
5354
/**
5455
* A JSONObject can be created with no content
5556
*/
@@ -165,6 +166,52 @@ public void verifyConstructor() {
165166
expected.similar(jaObjObj));
166167
}
167168

169+
/**
170+
* Tests Number serialization.
171+
*/
172+
@Test
173+
public void verifyNumberOutput(){
174+
JSONObject jsonObject = new JSONObject(new MyNumberContainer());
175+
String actual = jsonObject.toString();
176+
177+
// before wrapping of Number is allowed the number was converted as a bean
178+
String expected = "{\"myNumber\":{\"number\":42}}";
179+
//String expected = "{\"myNumber\":42}";
180+
assertEquals("Not Equal", expected , actual);
181+
182+
// put handles objects differently than the constructor.
183+
jsonObject = new JSONObject();
184+
jsonObject.put("myNumber", new MyNumber());
185+
actual = jsonObject.toString();
186+
// the output is the toString of the number as a number.
187+
expected = "{\"myNumber\":42}";
188+
assertEquals("Not Equal", expected , actual);
189+
190+
jsonObject = new JSONObject(Collections.singletonMap("myNumber", new AtomicInteger(42)));
191+
actual = jsonObject.toString();
192+
// before wrapping of Number is allowed the number was converted to a string
193+
expected = "{\"myNumber\":\"42\"}";
194+
assertEquals("Not Equal", expected , actual);
195+
196+
// put handles objects differently than the constructor.
197+
jsonObject = new JSONObject();
198+
jsonObject.put("myNumber", new AtomicInteger(42));
199+
actual = jsonObject.toString();
200+
expected = "{\"myNumber\":42}";
201+
assertEquals("Not Equal", expected , actual);
202+
203+
// verify Fraction output
204+
jsonObject = new JSONObject(Collections.singletonMap("myNumber", new Fraction(4,2)));
205+
assertEquals("Numerator", BigInteger.valueOf(4) , jsonObject.query("/myNumber/numerator"));
206+
assertEquals("Denominator", BigInteger.valueOf(2) , jsonObject.query("/myNumber/denominator"));
207+
208+
jsonObject = new JSONObject();
209+
jsonObject.put("myNumber", new Fraction(4,2));
210+
actual = jsonObject.toString();
211+
expected = "{\"myNumber\":4/2}"; // this is NOT valid JSON!!!!!!!!!!! BUG!
212+
assertEquals("Not Equal", expected , actual);
213+
}
214+
168215
/**
169216
* Verifies that the put Collection has backwards compatability with RAW types pre-java5.
170217
*/
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package org.json.junit;
2+
3+
import java.math.BigDecimal;
4+
5+
/**
6+
* Number override for testing. Number overrides should always override
7+
* toString, hashCode, and Equals.
8+
*
9+
* @see <a
10+
* href="https://docs.oracle.com/javase/tutorial/java/data/numberclasses.html">The
11+
* Numbers Classes</a>
12+
* @see <a
13+
* href="https://docs.oracle.com/javase/tutorial/java/data/numberformat.html">Formatting
14+
* Numeric Print Output</a>
15+
*
16+
* @author John Aylward
17+
*/
18+
public class MyNumber extends Number {
19+
private Number number = BigDecimal.valueOf(42);
20+
/**
21+
*/
22+
private static final long serialVersionUID = 1L;
23+
24+
/**
25+
* @return number!
26+
*/
27+
public Number getNumber() {
28+
return this.number;
29+
}
30+
31+
@Override
32+
public int intValue() {
33+
return getNumber().intValue();
34+
}
35+
36+
@Override
37+
public long longValue() {
38+
return getNumber().longValue();
39+
}
40+
41+
@Override
42+
public float floatValue() {
43+
return getNumber().floatValue();
44+
}
45+
46+
@Override
47+
public double doubleValue() {
48+
return getNumber().doubleValue();
49+
}
50+
51+
/* (non-Javadoc)
52+
* @see java.lang.Object#toString()
53+
*
54+
* Number overrides should in general always override the toString method.
55+
*/
56+
@Override
57+
public String toString() {
58+
return getNumber().toString();
59+
}
60+
61+
/* (non-Javadoc)
62+
* @see java.lang.Object#hashCode()
63+
*/
64+
@Override
65+
public int hashCode() {
66+
final int prime = 31;
67+
int result = 1;
68+
result = prime * result + ((this.number == null) ? 0 : this.number.hashCode());
69+
return result;
70+
}
71+
72+
/* (non-Javadoc)
73+
* @see java.lang.Object#equals(java.lang.Object)
74+
*/
75+
@Override
76+
public boolean equals(Object obj) {
77+
if (this == obj) {
78+
return true;
79+
}
80+
if (obj == null) {
81+
return false;
82+
}
83+
if (!(obj instanceof MyNumber)) {
84+
return false;
85+
}
86+
MyNumber other = (MyNumber) obj;
87+
if (this.number == null) {
88+
if (other.number != null) {
89+
return false;
90+
}
91+
} else if (!this.number.equals(other.number)) {
92+
return false;
93+
}
94+
return true;
95+
}
96+
97+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.json.junit;
2+
3+
/**
4+
* Class that holds our MyNumber override as a property.
5+
* @author John Aylward
6+
*/
7+
public class MyNumberContainer {
8+
private MyNumber myNumber = new MyNumber();
9+
/**
10+
* @return a MyNumber.
11+
*/
12+
public Number getMyNumber() {return this.myNumber;}
13+
}

0 commit comments

Comments
 (0)