diff --git a/moshi/src/main/java/com/squareup/moshi/BufferedSourceJsonReader.java b/moshi/src/main/java/com/squareup/moshi/BufferedSourceJsonReader.java index f31bdda..6362d01 100644 --- a/moshi/src/main/java/com/squareup/moshi/BufferedSourceJsonReader.java +++ b/moshi/src/main/java/com/squareup/moshi/BufferedSourceJsonReader.java @@ -17,6 +17,7 @@ package com.squareup.moshi; import java.io.EOFException; import java.io.IOException; +import java.math.BigDecimal; import okio.Buffer; import okio.BufferedSource; import okio.ByteString; @@ -718,15 +719,11 @@ final class BufferedSourceJsonReader extends JsonReader { } peeked = PEEKED_BUFFERED; - double asDouble; + long result; try { - asDouble = Double.parseDouble(peekedString); - } catch (NumberFormatException e) { - throw new JsonDataException("Expected a long but was " + peekedString - + " at path " + getPath()); - } - long result = (long) asDouble; - if (result != asDouble) { // Make sure no precision was lost casting to 'long'. + BigDecimal asDecimal = new BigDecimal(peekedString); + result = asDecimal.longValueExact(); + } catch (NumberFormatException | ArithmeticException e) { throw new JsonDataException("Expected a long but was " + peekedString + " at path " + getPath()); } diff --git a/moshi/src/test/java/com/squareup/moshi/BufferedSourceJsonReaderTest.java b/moshi/src/test/java/com/squareup/moshi/BufferedSourceJsonReaderTest.java index 8927e42..7a0c2b1 100644 --- a/moshi/src/test/java/com/squareup/moshi/BufferedSourceJsonReaderTest.java +++ b/moshi/src/test/java/com/squareup/moshi/BufferedSourceJsonReaderTest.java @@ -617,11 +617,7 @@ public final class BufferedSourceJsonReaderTest { } } - /** - * 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 { + @Test public void peekLargerThanLongMaxValue() throws IOException { JsonReader reader = newReader("[9223372036854775808]"); reader.setLenient(true); reader.beginArray(); @@ -633,11 +629,19 @@ public final class BufferedSourceJsonReaderTest { } } - /** - * This test fails because there's no double for -9223372036854775809, and our - * long parsing uses Double.parseDouble() for fractional values. - */ - @Test @Ignore public void peekLargerThanLongMinValue() throws IOException { + @Test public void precisionNotDiscarded() throws IOException { + JsonReader reader = newReader("[9223372036854775806.5]"); + reader.setLenient(true); + reader.beginArray(); + assertThat(reader.peek()).isEqualTo(NUMBER); + try { + reader.nextLong(); + fail(); + } catch (JsonDataException expected) { + } + } + + @Test public void peekLargerThanLongMinValue() throws IOException { JsonReader reader = newReader("[-9223372036854775809]"); reader.setLenient(true); reader.beginArray(); @@ -650,11 +654,7 @@ public final class BufferedSourceJsonReaderTest { assertThat(reader.nextDouble()).isEqualTo(-9223372036854775809d); } - /** - * 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 { + @Test public void highPrecisionLong() throws IOException { String json = "[9223372036854775806.000]"; JsonReader reader = newReader(json); reader.beginArray(); diff --git a/moshi/src/test/java/com/squareup/moshi/MoshiTest.java b/moshi/src/test/java/com/squareup/moshi/MoshiTest.java index 7033d1a..ab8b6f5 100644 --- a/moshi/src/test/java/com/squareup/moshi/MoshiTest.java +++ b/moshi/src/test/java/com/squareup/moshi/MoshiTest.java @@ -433,21 +433,19 @@ public final class MoshiTest { assertThat(adapter.fromJson("9223372036854775807")).isEqualTo(Long.MAX_VALUE); assertThat(adapter.toJson(Long.MAX_VALUE)).isEqualTo("9223372036854775807"); - // TODO: This is a bug? - assertThat(adapter.fromJson("9223372036854775808")).isEqualTo(Long.MAX_VALUE); // wtf? - //try { - // adapter.fromJson("9223372036854775808"); - // fail(); - //} catch (NumberFormatException expected) { - // assertThat(expected).hasMessage("Expected a long but was 9223372036854775808 at path $"); - //} - // - //try { - // adapter.fromJson("-9223372036854775809"); - // fail(); - //} catch (NumberFormatException expected) { - // assertThat(expected).hasMessage("Expected a long but was -9223372036854775809 at path $"); - //} + try { + adapter.fromJson("9223372036854775808"); + fail(); + } catch (JsonDataException expected) { + assertThat(expected).hasMessage("Expected a long but was 9223372036854775808 at path $"); + } + + try { + adapter.fromJson("-9223372036854775809"); + fail(); + } catch (JsonDataException expected) { + assertThat(expected).hasMessage("Expected a long but was -9223372036854775809 at path $"); + } // Nulls not allowed for long.class try {