Skip to content

Commit

Permalink
fix #167, if dot found, should always parse as double
Browse files Browse the repository at this point in the history
  • Loading branch information
taowen committed Mar 5, 2018
1 parent e21a29f commit 68c985b
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 14 deletions.
31 changes: 24 additions & 7 deletions src/main/java/com/jsoniter/IterImplForStreaming.java
Original file line number Diff line number Diff line change
Expand Up @@ -539,15 +539,22 @@ static int readIntSlowPath(final JsonIterator iter, int value) throws IOExceptio

public static final double readDoubleSlowPath(final JsonIterator iter) throws IOException {
try {
String numberAsStr = readNumber(iter);
return Double.valueOf(numberAsStr);
numberChars numberChars = readNumber(iter);
return Double.valueOf(new String(numberChars.chars, 0, numberChars.charsLength));
} catch (NumberFormatException e) {
throw iter.reportError("readDoubleSlowPath", e.toString());
}
}

public static final String readNumber(final JsonIterator iter) throws IOException {
static class numberChars {
char[] chars;
int charsLength;
boolean dotFound;
}

public static final numberChars readNumber(final JsonIterator iter) throws IOException {
int j = 0;
boolean dotFound = false;
for (; ; ) {
for (int i = iter.head; i < iter.tail; i++) {
if (j == iter.reusableChars.length) {
Expand All @@ -557,11 +564,13 @@ public static final String readNumber(final JsonIterator iter) throws IOExceptio
}
byte c = iter.buf[i];
switch (c) {
case '-':
case '+':
case '.':
case 'e':
case 'E':
dotFound = true;
// fallthrough
case '-':
case '+':
case '0':
case '1':
case '2':
Expand All @@ -576,12 +585,20 @@ public static final String readNumber(final JsonIterator iter) throws IOExceptio
break;
default:
iter.head = i;
return new String(iter.reusableChars, 0, j);
numberChars numberChars = new numberChars();
numberChars.chars = iter.reusableChars;
numberChars.charsLength = j;
numberChars.dotFound = dotFound;
return numberChars;
}
}
if (!IterImpl.loadMore(iter)) {
iter.head = iter.tail;
return new String(iter.reusableChars, 0, j);
numberChars numberChars = new numberChars();
numberChars.chars = iter.reusableChars;
numberChars.charsLength = j;
numberChars.dotFound = dotFound;
return numberChars;
}
}
}
Expand Down
20 changes: 14 additions & 6 deletions src/main/java/com/jsoniter/JsonIterator.java
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@ public final boolean readArray() throws IOException {
}

public String readNumberAsString() throws IOException {
return IterImplForStreaming.readNumber(this);
IterImplForStreaming.numberChars numberChars = IterImplForStreaming.readNumber(this);
return new String(numberChars.chars, 0, numberChars.charsLength);
}

public static interface ReadArrayCallback {
Expand Down Expand Up @@ -239,7 +240,8 @@ public final BigDecimal readBigDecimal() throws IOException {
if (valueType != ValueType.NUMBER) {
throw reportError("readBigDecimal", "not number");
}
return new BigDecimal(IterImplForStreaming.readNumber(this));
IterImplForStreaming.numberChars numberChars = IterImplForStreaming.readNumber(this);
return new BigDecimal(numberChars.chars, 0, numberChars.charsLength);
}

public final BigInteger readBigInteger() throws IOException {
Expand All @@ -252,7 +254,8 @@ public final BigInteger readBigInteger() throws IOException {
if (valueType != ValueType.NUMBER) {
throw reportError("readBigDecimal", "not number");
}
return new BigInteger(IterImplForStreaming.readNumber(this));
IterImplForStreaming.numberChars numberChars = IterImplForStreaming.readNumber(this);
return new BigInteger(new String(numberChars.chars, 0, numberChars.charsLength));
}

public final Any readAny() throws IOException {
Expand Down Expand Up @@ -288,9 +291,14 @@ public final Object read() throws IOException {
case STRING:
return readString();
case NUMBER:
double number = readDouble();
if (number == Math.floor(number) && !Double.isInfinite(number)) {
long longNumber = (long) number;
IterImplForStreaming.numberChars numberChars = IterImplForStreaming.readNumber(this);
Double number = Double.valueOf(new String(numberChars.chars, 0, numberChars.charsLength));
if (numberChars.dotFound) {
return number;
}
double doubleNumber = number;
if (doubleNumber == Math.floor(doubleNumber) && !Double.isInfinite(doubleNumber)) {
long longNumber = (long) doubleNumber;
if (longNumber <= Integer.MAX_VALUE && longNumber >= Integer.MIN_VALUE) {
return (int) longNumber;
}
Expand Down
3 changes: 2 additions & 1 deletion src/test/java/com/jsoniter/IterImplForStreamingTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ public class IterImplForStreamingTest extends TestCase {
public void testReadMaxDouble() throws Exception {
String maxDouble = "1.7976931348623157e+308";
JsonIterator iter = JsonIterator.parse("1.7976931348623157e+308");
String number = IterImplForStreaming.readNumber(iter);
IterImplForStreaming.numberChars numberChars = IterImplForStreaming.readNumber(iter);
String number = new String(numberChars.chars, 0, numberChars.charsLength);
assertEquals(maxDouble, number);
}
}
3 changes: 3 additions & 0 deletions src/test/java/com/jsoniter/TestFloat.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.jsoniter;

import com.fasterxml.jackson.databind.ObjectMapper;
import junit.framework.TestCase;
import org.junit.experimental.categories.Category;

Expand Down Expand Up @@ -86,5 +87,7 @@ public void testBigDecimal() {
public void testChooseDouble() {
Object number = JsonIterator.deserialize("1.1", Object.class);
assertEquals(1.1, number);
number = JsonIterator.deserialize("1.0", Object.class);
assertEquals(1.0, number);
}
}

0 comments on commit 68c985b

Please sign in to comment.