Skip to content

Commit aac802b

Browse files
liedtkemcowtowncoder
authored andcommitted
Optimize IonParser.getNumberType() using IonReader.getIntegerSize(), read Ion decimals as BigDecimal to support arbitraty precision
1 parent 2d25d1b commit aac802b

File tree

2 files changed

+40
-20
lines changed

2 files changed

+40
-20
lines changed

ion/src/main/java/com/fasterxml/jackson/dataformat/ion/IonParser.java

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -268,19 +268,17 @@ public NumberType getNumberType() throws IOException
268268
// harder to pin down exact type. But let's try some checks still.
269269
switch (type) {
270270
case DECIMAL:
271-
// Could be float, double or big decimal; hard to check, let's choose doubel
272-
return NumberType.DOUBLE;
271+
//Ion decimals can be arbitrary precision, need to read as big decimal
272+
return NumberType.BIG_DECIMAL;
273273
case INT:
274-
// TODO: It would be good if IonReader directly told us which type to use.
275-
BigInteger i = _reader.bigIntegerValue();
276-
if ((i.compareTo(LONG_MIN_VALUE) < 0) ||
277-
(i.compareTo(LONG_MAX_VALUE) > 0)) {
278-
return NumberType.BIG_INTEGER;
279-
} else if ((i.compareTo(INT_MIN_VALUE) < 0) ||
280-
(i.compareTo(INT_MAX_VALUE) > 0)) {
281-
return NumberType.LONG;
282-
} else {
274+
IntegerSize size = _reader.getIntegerSize();
275+
switch (size) {
276+
case INT:
283277
return NumberType.INT;
278+
case LONG:
279+
return NumberType.LONG;
280+
default:
281+
return NumberType.BIG_INTEGER;
284282
}
285283
case FLOAT:
286284
return NumberType.DOUBLE;

ion/src/test/java/com/fasterxml/jackson/dataformat/ion/IonParserTest.java

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,47 +21,69 @@
2121

2222
import org.junit.Assert;
2323

24+
import com.amazon.ion.IonDecimal;
2425
import com.amazon.ion.IonReader;
2526
import com.amazon.ion.IonSystem;
2627
import com.amazon.ion.IonValue;
2728
import com.amazon.ion.system.IonSystemBuilder;
2829

2930
import java.io.IOException;
31+
import java.math.BigDecimal;
3032
import java.math.BigInteger;
3133
import org.junit.Test;
3234

3335
@SuppressWarnings("resource")
3436
public class IonParserTest
3537
{
3638
@Test
37-
public void testGetNumberType() throws Exception {
39+
public void testGetNumberTypeAndValue() throws Exception {
3840
IonSystem ion = IonSystemBuilder.standard().build();
3941

40-
IonValue ionInt = ion.newInt(Integer.MAX_VALUE);
42+
Integer intValue = Integer.MAX_VALUE;
43+
IonValue ionInt = ion.newInt(intValue);
4144
IonParser intParser = new IonFactory().createParser(ionInt);
4245
Assert.assertEquals(JsonToken.VALUE_NUMBER_INT, intParser.nextToken());
4346
Assert.assertEquals(JsonParser.NumberType.INT, intParser.getNumberType());
47+
Assert.assertEquals(intValue, intParser.getNumberValue());
4448

45-
IonValue ionLong = ion.newInt(Long.MAX_VALUE);
49+
Long longValue = Long.MAX_VALUE;
50+
IonValue ionLong = ion.newInt(longValue);
4651
IonParser longParser = new IonFactory().createParser(ionLong);
4752
Assert.assertEquals(JsonToken.VALUE_NUMBER_INT, longParser.nextToken());
4853
Assert.assertEquals(JsonParser.NumberType.LONG, longParser.getNumberType());
54+
Assert.assertEquals(longValue, longParser.getNumberValue());
4955

50-
IonValue ionBigInt = ion.newInt(new BigInteger(Long.MAX_VALUE + "1"));
56+
BigInteger bigIntValue = new BigInteger(Long.MAX_VALUE + "1");
57+
IonValue ionBigInt = ion.newInt(bigIntValue);
5158
IonParser bigIntParser = new IonFactory().createParser(ionBigInt);
5259
Assert.assertEquals(JsonToken.VALUE_NUMBER_INT, bigIntParser.nextToken());
5360
Assert.assertEquals(JsonParser.NumberType.BIG_INTEGER, bigIntParser.getNumberType());
61+
Assert.assertEquals(bigIntValue, bigIntParser.getNumberValue());
5462

55-
// JoiParser is currently deficient with decimals -- all decimals are reported as Double. So this is all we can test.
56-
IonValue ionDecimal = ion.newDecimal(Double.MAX_VALUE);
57-
IonParser floatParser = new IonFactory().createParser(ionDecimal);
63+
Double decimalValue = Double.MAX_VALUE;
64+
IonValue ionDecimal = ion.newDecimal(decimalValue);
65+
IonParser decimalParser = new IonFactory().createParser(ionDecimal);
66+
Assert.assertEquals(JsonToken.VALUE_NUMBER_FLOAT, decimalParser.nextToken());
67+
Assert.assertEquals(JsonParser.NumberType.BIG_DECIMAL, decimalParser.getNumberType());
68+
Assert.assertTrue(new BigDecimal("" + decimalValue).compareTo((BigDecimal)decimalParser.getNumberValue()) == 0);
69+
70+
Double floatValue = Double.MAX_VALUE;
71+
IonValue ionFloat = ion.newFloat(floatValue);
72+
IonParser floatParser = new IonFactory().createParser(ionFloat);
5873
Assert.assertEquals(JsonToken.VALUE_NUMBER_FLOAT, floatParser.nextToken());
5974
Assert.assertEquals(JsonParser.NumberType.DOUBLE, floatParser.getNumberType());
75+
Assert.assertEquals(floatValue, floatParser.getNumberValue());
76+
77+
BigDecimal bigDecimalValue = new BigDecimal(Double.MAX_VALUE + "1");
78+
IonValue ionBigDecimal = ion.newDecimal(bigDecimalValue);
79+
IonParser bigDecimalParser = new IonFactory().createParser(ionBigDecimal);
80+
Assert.assertEquals(JsonToken.VALUE_NUMBER_FLOAT, bigDecimalParser.nextToken());
81+
Assert.assertEquals(JsonParser.NumberType.BIG_DECIMAL, bigDecimalParser.getNumberType());
82+
Assert.assertTrue(bigDecimalValue.compareTo((BigDecimal)bigDecimalParser.getNumberValue()) == 0);
6083
}
6184

6285
@Test
63-
public void testFloatType() throws IOException
64-
{
86+
public void testFloatType() throws IOException {
6587
final byte[] data = "{ score:0.291e0 }".getBytes();
6688
IonSystem ion = IonSystemBuilder.standard().build();
6789
final IonValue ionFloat = ion.newFloat(Float.MAX_VALUE);

0 commit comments

Comments
 (0)