Fix Long parsing for big values.

This commit is contained in:
Serj Lotutovici
2016-11-07 14:54:13 +01:00
committed by jwilson
parent f667733ec7
commit 38a06b080d
3 changed files with 33 additions and 38 deletions

View File

@@ -17,6 +17,7 @@ package com.squareup.moshi;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal;
import okio.Buffer; import okio.Buffer;
import okio.BufferedSource; import okio.BufferedSource;
import okio.ByteString; import okio.ByteString;
@@ -718,15 +719,11 @@ final class BufferedSourceJsonReader extends JsonReader {
} }
peeked = PEEKED_BUFFERED; peeked = PEEKED_BUFFERED;
double asDouble; long result;
try { try {
asDouble = Double.parseDouble(peekedString); BigDecimal asDecimal = new BigDecimal(peekedString);
} catch (NumberFormatException e) { result = asDecimal.longValueExact();
throw new JsonDataException("Expected a long but was " + peekedString } catch (NumberFormatException | ArithmeticException e) {
+ " at path " + getPath());
}
long result = (long) asDouble;
if (result != asDouble) { // Make sure no precision was lost casting to 'long'.
throw new JsonDataException("Expected a long but was " + peekedString throw new JsonDataException("Expected a long but was " + peekedString
+ " at path " + getPath()); + " at path " + getPath());
} }

View File

@@ -617,11 +617,7 @@ public final class BufferedSourceJsonReaderTest {
} }
} }
/** @Test public void peekLargerThanLongMaxValue() throws IOException {
* This test fails because there's no double for 9223372036854775808, and our
* long parsing uses Double.parseDouble() for fractional values.
*/
@Test @Ignore public void peekLargerThanLongMaxValue() throws IOException {
JsonReader reader = newReader("[9223372036854775808]"); JsonReader reader = newReader("[9223372036854775808]");
reader.setLenient(true); reader.setLenient(true);
reader.beginArray(); reader.beginArray();
@@ -633,11 +629,19 @@ public final class BufferedSourceJsonReaderTest {
} }
} }
/** @Test public void precisionNotDiscarded() throws IOException {
* This test fails because there's no double for -9223372036854775809, and our JsonReader reader = newReader("[9223372036854775806.5]");
* long parsing uses Double.parseDouble() for fractional values. reader.setLenient(true);
*/ reader.beginArray();
@Test @Ignore public void peekLargerThanLongMinValue() throws IOException { assertThat(reader.peek()).isEqualTo(NUMBER);
try {
reader.nextLong();
fail();
} catch (JsonDataException expected) {
}
}
@Test public void peekLargerThanLongMinValue() throws IOException {
JsonReader reader = newReader("[-9223372036854775809]"); JsonReader reader = newReader("[-9223372036854775809]");
reader.setLenient(true); reader.setLenient(true);
reader.beginArray(); reader.beginArray();
@@ -650,11 +654,7 @@ public final class BufferedSourceJsonReaderTest {
assertThat(reader.nextDouble()).isEqualTo(-9223372036854775809d); assertThat(reader.nextDouble()).isEqualTo(-9223372036854775809d);
} }
/** @Test public void highPrecisionLong() throws IOException {
* This test fails because there's no double for 9223372036854775806, and
* our long parsing uses Double.parseDouble() for fractional values.
*/
@Test @Ignore public void highPrecisionLong() throws IOException {
String json = "[9223372036854775806.000]"; String json = "[9223372036854775806.000]";
JsonReader reader = newReader(json); JsonReader reader = newReader(json);
reader.beginArray(); reader.beginArray();

View File

@@ -433,21 +433,19 @@ public final class MoshiTest {
assertThat(adapter.fromJson("9223372036854775807")).isEqualTo(Long.MAX_VALUE); assertThat(adapter.fromJson("9223372036854775807")).isEqualTo(Long.MAX_VALUE);
assertThat(adapter.toJson(Long.MAX_VALUE)).isEqualTo("9223372036854775807"); assertThat(adapter.toJson(Long.MAX_VALUE)).isEqualTo("9223372036854775807");
// TODO: This is a bug? try {
assertThat(adapter.fromJson("9223372036854775808")).isEqualTo(Long.MAX_VALUE); // wtf? adapter.fromJson("9223372036854775808");
//try { fail();
// adapter.fromJson("9223372036854775808"); } catch (JsonDataException expected) {
// fail(); assertThat(expected).hasMessage("Expected a long but was 9223372036854775808 at path $");
//} catch (NumberFormatException expected) { }
// assertThat(expected).hasMessage("Expected a long but was 9223372036854775808 at path $");
//} try {
// adapter.fromJson("-9223372036854775809");
//try { fail();
// adapter.fromJson("-9223372036854775809"); } catch (JsonDataException expected) {
// fail(); assertThat(expected).hasMessage("Expected a long but was -9223372036854775809 at path $");
//} catch (NumberFormatException expected) { }
// assertThat(expected).hasMessage("Expected a long but was -9223372036854775809 at path $");
//}
// Nulls not allowed for long.class // Nulls not allowed for long.class
try { try {