/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.gson.stream; import java.io.EOFException; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.Arrays; import junit.framework.TestCase; import static com.google.gson.stream.JsonToken.BEGIN_ARRAY; import static com.google.gson.stream.JsonToken.BEGIN_OBJECT; import static com.google.gson.stream.JsonToken.BOOLEAN; import static com.google.gson.stream.JsonToken.END_ARRAY; import static com.google.gson.stream.JsonToken.END_OBJECT; import static com.google.gson.stream.JsonToken.NAME; import static com.google.gson.stream.JsonToken.NULL; import static com.google.gson.stream.JsonToken.NUMBER; import static com.google.gson.stream.JsonToken.STRING; @SuppressWarnings("resource") public final class JsonReaderTest extends TestCase { public void testReadArray() throws IOException { JsonReader reader = new JsonReader(reader("[true, true]")); reader.beginArray(); assertEquals(true, reader.nextBoolean()); assertEquals(true, reader.nextBoolean()); reader.endArray(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testReadEmptyArray() throws IOException { JsonReader reader = new JsonReader(reader("[]")); reader.beginArray(); assertFalse(reader.hasNext()); reader.endArray(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testReadObject() throws IOException { JsonReader reader = new JsonReader(reader( "{\"a\": \"android\", \"b\": \"banana\"}")); reader.beginObject(); assertEquals("a", reader.nextName()); assertEquals("android", reader.nextString()); assertEquals("b", reader.nextName()); assertEquals("banana", reader.nextString()); reader.endObject(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testReadEmptyObject() throws IOException { JsonReader reader = new JsonReader(reader("{}")); reader.beginObject(); assertFalse(reader.hasNext()); reader.endObject(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testSkipArray() throws IOException { JsonReader reader = new JsonReader(reader( "{\"a\": [\"one\", \"two\", \"three\"], \"b\": 123}")); reader.beginObject(); assertEquals("a", reader.nextName()); reader.skipValue(); assertEquals("b", reader.nextName()); assertEquals(123, reader.nextInt()); reader.endObject(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testSkipArrayAfterPeek() throws Exception { JsonReader reader = new JsonReader(reader( "{\"a\": [\"one\", \"two\", \"three\"], \"b\": 123}")); reader.beginObject(); assertEquals("a", reader.nextName()); assertEquals(BEGIN_ARRAY, reader.peek()); reader.skipValue(); assertEquals("b", reader.nextName()); assertEquals(123, reader.nextInt()); reader.endObject(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testSkipTopLevelObject() throws Exception { JsonReader reader = new JsonReader(reader( "{\"a\": [\"one\", \"two\", \"three\"], \"b\": 123}")); reader.skipValue(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testSkipObject() throws IOException { JsonReader reader = new JsonReader(reader( "{\"a\": { \"c\": [], \"d\": [true, true, {}] }, \"b\": \"banana\"}")); reader.beginObject(); assertEquals("a", reader.nextName()); reader.skipValue(); assertEquals("b", reader.nextName()); reader.skipValue(); reader.endObject(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testSkipObjectAfterPeek() throws Exception { String json = "{" + " \"one\": { \"num\": 1 }" + ", \"two\": { \"num\": 2 }" + ", \"three\": { \"num\": 3 }" + "}"; JsonReader reader = new JsonReader(reader(json)); reader.beginObject(); assertEquals("one", reader.nextName()); assertEquals(BEGIN_OBJECT, reader.peek()); reader.skipValue(); assertEquals("two", reader.nextName()); assertEquals(BEGIN_OBJECT, reader.peek()); reader.skipValue(); assertEquals("three", reader.nextName()); reader.skipValue(); reader.endObject(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testSkipInteger() throws IOException { JsonReader reader = new JsonReader(reader( "{\"a\":123456789,\"b\":-123456789}")); reader.beginObject(); assertEquals("a", reader.nextName()); reader.skipValue(); assertEquals("b", reader.nextName()); reader.skipValue(); reader.endObject(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testSkipDouble() throws IOException { JsonReader reader = new JsonReader(reader( "{\"a\":-123.456e-789,\"b\":123456789.0}")); reader.beginObject(); assertEquals("a", reader.nextName()); reader.skipValue(); assertEquals("b", reader.nextName()); reader.skipValue(); reader.endObject(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testHelloWorld() throws IOException { String json = "{\n" + " \"hello\": true,\n" + " \"foo\": [\"world\"]\n" + "}"; JsonReader reader = new JsonReader(reader(json)); reader.beginObject(); assertEquals("hello", reader.nextName()); assertEquals(true, reader.nextBoolean()); assertEquals("foo", reader.nextName()); reader.beginArray(); assertEquals("world", reader.nextString()); reader.endArray(); reader.endObject(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testInvalidJsonInput() throws IOException { String json = "{\n" + " \"h\\ello\": true,\n" + " \"foo\": [\"world\"]\n" + "}"; JsonReader reader = new JsonReader(reader(json)); reader.beginObject(); try { reader.nextName(); fail(); } catch (IOException expected) { } } public void testNulls() { try { new JsonReader(null); fail(); } catch (NullPointerException expected) { } } public void testEmptyString() { try { new JsonReader(reader("")).beginArray(); fail(); } catch (IOException expected) { } try { new JsonReader(reader("")).beginObject(); fail(); } catch (IOException expected) { } } public void testCharacterUnescaping() throws IOException { String json = "[\"a\"," + "\"a\\\"\"," + "\"\\\"\"," + "\":\"," + "\",\"," + "\"\\b\"," + "\"\\f\"," + "\"\\n\"," + "\"\\r\"," + "\"\\t\"," + "\" \"," + "\"\\\\\"," + "\"{\"," + "\"}\"," + "\"[\"," + "\"]\"," + "\"\\u0000\"," + "\"\\u0019\"," + "\"\\u20AC\"" + "]"; JsonReader reader = new JsonReader(reader(json)); reader.beginArray(); assertEquals("a", reader.nextString()); assertEquals("a\"", reader.nextString()); assertEquals("\"", reader.nextString()); assertEquals(":", reader.nextString()); assertEquals(",", reader.nextString()); assertEquals("\b", reader.nextString()); assertEquals("\f", reader.nextString()); assertEquals("\n", reader.nextString()); assertEquals("\r", reader.nextString()); assertEquals("\t", reader.nextString()); assertEquals(" ", reader.nextString()); assertEquals("\\", reader.nextString()); assertEquals("{", reader.nextString()); assertEquals("}", reader.nextString()); assertEquals("[", reader.nextString()); assertEquals("]", reader.nextString()); assertEquals("\0", reader.nextString()); assertEquals("\u0019", reader.nextString()); assertEquals("\u20AC", reader.nextString()); reader.endArray(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testUnescapingInvalidCharacters() throws IOException { String json = "[\"\\u000g\"]"; JsonReader reader = new JsonReader(reader(json)); reader.beginArray(); try { reader.nextString(); fail(); } catch (NumberFormatException expected) { } } public void testUnescapingTruncatedCharacters() throws IOException { String json = "[\"\\u000"; JsonReader reader = new JsonReader(reader(json)); reader.beginArray(); try { reader.nextString(); fail(); } catch (IOException expected) { } } public void testUnescapingTruncatedSequence() throws IOException { String json = "[\"\\"; JsonReader reader = new JsonReader(reader(json)); reader.beginArray(); try { reader.nextString(); fail(); } catch (IOException expected) { } } public void testIntegersWithFractionalPartSpecified() throws IOException { JsonReader reader = new JsonReader(reader("[1.0,1.0,1.0]")); reader.beginArray(); assertEquals(1.0, reader.nextDouble()); assertEquals(1, reader.nextInt()); assertEquals(1L, reader.nextLong()); } public void testDoubles() throws IOException { String json = "[-0.0," + "1.0," + "1.7976931348623157E308," + "4.9E-324," + "0.0," + "-0.5," + "2.2250738585072014E-308," + "3.141592653589793," + "2.718281828459045]"; JsonReader reader = new JsonReader(reader(json)); reader.beginArray(); assertEquals(-0.0, reader.nextDouble()); assertEquals(1.0, reader.nextDouble()); assertEquals(1.7976931348623157E308, reader.nextDouble()); assertEquals(4.9E-324, reader.nextDouble()); assertEquals(0.0, reader.nextDouble()); assertEquals(-0.5, reader.nextDouble()); assertEquals(2.2250738585072014E-308, reader.nextDouble()); assertEquals(3.141592653589793, reader.nextDouble()); assertEquals(2.718281828459045, reader.nextDouble()); reader.endArray(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testStrictNonFiniteDoubles() throws IOException { String json = "[NaN]"; JsonReader reader = new JsonReader(reader(json)); reader.beginArray(); try { reader.nextDouble(); fail(); } catch (MalformedJsonException expected) { } } public void testStrictQuotedNonFiniteDoubles() throws IOException { String json = "[\"NaN\"]"; JsonReader reader = new JsonReader(reader(json)); reader.beginArray(); try { reader.nextDouble(); fail(); } catch (MalformedJsonException expected) { } } public void testLenientNonFiniteDoubles() throws IOException { String json = "[NaN, -Infinity, Infinity]"; JsonReader reader = new JsonReader(reader(json)); reader.setLenient(true); reader.beginArray(); assertTrue(Double.isNaN(reader.nextDouble())); assertEquals(Double.NEGATIVE_INFINITY, reader.nextDouble()); assertEquals(Double.POSITIVE_INFINITY, reader.nextDouble()); reader.endArray(); } public void testLenientQuotedNonFiniteDoubles() throws IOException { String json = "[\"NaN\", \"-Infinity\", \"Infinity\"]"; JsonReader reader = new JsonReader(reader(json)); reader.setLenient(true); reader.beginArray(); assertTrue(Double.isNaN(reader.nextDouble())); assertEquals(Double.NEGATIVE_INFINITY, reader.nextDouble()); assertEquals(Double.POSITIVE_INFINITY, reader.nextDouble()); reader.endArray(); } public void testStrictNonFiniteDoublesWithSkipValue() throws IOException { String json = "[NaN]"; JsonReader reader = new JsonReader(reader(json)); reader.beginArray(); try { reader.skipValue(); fail(); } catch (MalformedJsonException expected) { } } public void testLongs() throws IOException { String json = "[0,0,0," + "1,1,1," + "-1,-1,-1," + "-9223372036854775808," + "9223372036854775807]"; JsonReader reader = new JsonReader(reader(json)); reader.beginArray(); assertEquals(0L, reader.nextLong()); assertEquals(0, reader.nextInt()); assertEquals(0.0, reader.nextDouble()); assertEquals(1L, reader.nextLong()); assertEquals(1, reader.nextInt()); assertEquals(1.0, reader.nextDouble()); assertEquals(-1L, reader.nextLong()); assertEquals(-1, reader.nextInt()); assertEquals(-1.0, reader.nextDouble()); try { reader.nextInt(); fail(); } catch (NumberFormatException expected) { } assertEquals(Long.MIN_VALUE, reader.nextLong()); try { reader.nextInt(); fail(); } catch (NumberFormatException expected) { } assertEquals(Long.MAX_VALUE, reader.nextLong()); reader.endArray(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void disabled_testNumberWithOctalPrefix() throws IOException { String json = "[01]"; JsonReader reader = new JsonReader(reader(json)); reader.beginArray(); try { reader.peek(); fail(); } catch (MalformedJsonException expected) { } try { reader.nextInt(); fail(); } catch (MalformedJsonException expected) { } try { reader.nextLong(); fail(); } catch (MalformedJsonException expected) { } try { reader.nextDouble(); fail(); } catch (MalformedJsonException expected) { } assertEquals("01", reader.nextString()); reader.endArray(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testBooleans() throws IOException { JsonReader reader = new JsonReader(reader("[true,false]")); reader.beginArray(); assertEquals(true, reader.nextBoolean()); assertEquals(false, reader.nextBoolean()); reader.endArray(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testPeekingUnquotedStringsPrefixedWithBooleans() throws IOException { JsonReader reader = new JsonReader(reader("[truey]")); reader.setLenient(true); reader.beginArray(); assertEquals(STRING, reader.peek()); try { reader.nextBoolean(); fail(); } catch (IllegalStateException expected) { } assertEquals("truey", reader.nextString()); reader.endArray(); } public void testMalformedNumbers() throws IOException { assertNotANumber("-"); assertNotANumber("."); // exponent lacks digit assertNotANumber("e"); assertNotANumber("0e"); assertNotANumber(".e"); assertNotANumber("0.e"); assertNotANumber("-.0e"); // no integer assertNotANumber("e1"); assertNotANumber(".e1"); assertNotANumber("-e1"); // trailing characters assertNotANumber("1x"); assertNotANumber("1.1x"); assertNotANumber("1e1x"); assertNotANumber("1ex"); assertNotANumber("1.1ex"); assertNotANumber("1.1e1x"); // fraction has no digit assertNotANumber("0."); assertNotANumber("-0."); assertNotANumber("0.e1"); assertNotANumber("-0.e1"); // no leading digit assertNotANumber(".0"); assertNotANumber("-.0"); assertNotANumber(".0e1"); assertNotANumber("-.0e1"); } private void assertNotANumber(String s) throws IOException { JsonReader reader = new JsonReader(reader("[" + s + "]")); reader.setLenient(true); reader.beginArray(); assertEquals(JsonToken.STRING, reader.peek()); assertEquals(s, reader.nextString()); reader.endArray(); } public void testPeekingUnquotedStringsPrefixedWithIntegers() throws IOException { JsonReader reader = new JsonReader(reader("[12.34e5x]")); reader.setLenient(true); reader.beginArray(); assertEquals(STRING, reader.peek()); try { reader.nextInt(); fail(); } catch (NumberFormatException expected) { } assertEquals("12.34e5x", reader.nextString()); } public void testPeekLongMinValue() throws IOException { JsonReader reader = new JsonReader(reader("[-9223372036854775808]")); reader.setLenient(true); reader.beginArray(); assertEquals(NUMBER, reader.peek()); assertEquals(-9223372036854775808L, reader.nextLong()); } public void testPeekLongMaxValue() throws IOException { JsonReader reader = new JsonReader(reader("[9223372036854775807]")); reader.setLenient(true); reader.beginArray(); assertEquals(NUMBER, reader.peek()); assertEquals(9223372036854775807L, reader.nextLong()); } public void testLongLargerThanMaxLongThatWrapsAround() throws IOException { JsonReader reader = new JsonReader(reader("[22233720368547758070]")); reader.setLenient(true); reader.beginArray(); assertEquals(NUMBER, reader.peek()); try { reader.nextLong(); fail(); } catch (NumberFormatException expected) { } } public void testLongLargerThanMinLongThatWrapsAround() throws IOException { JsonReader reader = new JsonReader(reader("[-22233720368547758070]")); reader.setLenient(true); reader.beginArray(); assertEquals(NUMBER, reader.peek()); try { reader.nextLong(); fail(); } catch (NumberFormatException expected) { } } /** * This test fails because there's no double for 9223372036854775808, and our * long parsing uses Double.parseDouble() for fractional values. */ public void disabled_testPeekLargerThanLongMaxValue() throws IOException { JsonReader reader = new JsonReader(reader("[9223372036854775808]")); reader.setLenient(true); reader.beginArray(); assertEquals(NUMBER, reader.peek()); try { reader.nextLong(); fail(); } catch (NumberFormatException e) { } } /** * This test fails because there's no double for -9223372036854775809, and our * long parsing uses Double.parseDouble() for fractional values. */ public void disabled_testPeekLargerThanLongMinValue() throws IOException { JsonReader reader = new JsonReader(reader("[-9223372036854775809]")); reader.setLenient(true); reader.beginArray(); assertEquals(NUMBER, reader.peek()); try { reader.nextLong(); fail(); } catch (NumberFormatException expected) { } assertEquals(-9223372036854775809d, reader.nextDouble()); } /** * This test fails because there's no double for 9223372036854775806, and * our long parsing uses Double.parseDouble() for fractional values. */ public void disabled_testHighPrecisionLong() throws IOException { String json = "[9223372036854775806.000]"; JsonReader reader = new JsonReader(reader(json)); reader.beginArray(); assertEquals(9223372036854775806L, reader.nextLong()); reader.endArray(); } public void testPeekMuchLargerThanLongMinValue() throws IOException { JsonReader reader = new JsonReader(reader("[-92233720368547758080]")); reader.setLenient(true); reader.beginArray(); assertEquals(NUMBER, reader.peek()); try { reader.nextLong(); fail(); } catch (NumberFormatException expected) { } assertEquals(-92233720368547758080d, reader.nextDouble()); } public void testQuotedNumberWithEscape() throws IOException { JsonReader reader = new JsonReader(reader("[\"12\u00334\"]")); reader.setLenient(true); reader.beginArray(); assertEquals(STRING, reader.peek()); assertEquals(1234, reader.nextInt()); } public void testMixedCaseLiterals() throws IOException { JsonReader reader = new JsonReader(reader("[True,TruE,False,FALSE,NULL,nulL]")); reader.beginArray(); assertEquals(true, reader.nextBoolean()); assertEquals(true, reader.nextBoolean()); assertEquals(false, reader.nextBoolean()); assertEquals(false, reader.nextBoolean()); reader.nextNull(); reader.nextNull(); reader.endArray(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testMissingValue() throws IOException { JsonReader reader = new JsonReader(reader("{\"a\":}")); reader.beginObject(); assertEquals("a", reader.nextName()); try { reader.nextString(); fail(); } catch (IOException expected) { } } public void testPrematureEndOfInput() throws IOException { JsonReader reader = new JsonReader(reader("{\"a\":true,")); reader.beginObject(); assertEquals("a", reader.nextName()); assertEquals(true, reader.nextBoolean()); try { reader.nextName(); fail(); } catch (IOException expected) { } } public void testPrematurelyClosed() throws IOException { try { JsonReader reader = new JsonReader(reader("{\"a\":[]}")); reader.beginObject(); reader.close(); reader.nextName(); fail(); } catch (IllegalStateException expected) { } try { JsonReader reader = new JsonReader(reader("{\"a\":[]}")); reader.close(); reader.beginObject(); fail(); } catch (IllegalStateException expected) { } try { JsonReader reader = new JsonReader(reader("{\"a\":true}")); reader.beginObject(); reader.nextName(); reader.peek(); reader.close(); reader.nextBoolean(); fail(); } catch (IllegalStateException expected) { } } public void testNextFailuresDoNotAdvance() throws IOException { JsonReader reader = new JsonReader(reader("{\"a\":true}")); reader.beginObject(); try { reader.nextString(); fail(); } catch (IllegalStateException expected) { } assertEquals("a", reader.nextName()); try { reader.nextName(); fail(); } catch (IllegalStateException expected) { } try { reader.beginArray(); fail(); } catch (IllegalStateException expected) { } try { reader.endArray(); fail(); } catch (IllegalStateException expected) { } try { reader.beginObject(); fail(); } catch (IllegalStateException expected) { } try { reader.endObject(); fail(); } catch (IllegalStateException expected) { } assertEquals(true, reader.nextBoolean()); try { reader.nextString(); fail(); } catch (IllegalStateException expected) { } try { reader.nextName(); fail(); } catch (IllegalStateException expected) { } try { reader.beginArray(); fail(); } catch (IllegalStateException expected) { } try { reader.endArray(); fail(); } catch (IllegalStateException expected) { } reader.endObject(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); reader.close(); } public void testIntegerMismatchFailuresDoNotAdvance() throws IOException { JsonReader reader = new JsonReader(reader("[1.5]")); reader.beginArray(); try { reader.nextInt(); fail(); } catch (NumberFormatException expected) { } assertEquals(1.5d, reader.nextDouble()); reader.endArray(); } public void testStringNullIsNotNull() throws IOException { JsonReader reader = new JsonReader(reader("[\"null\"]")); reader.beginArray(); try { reader.nextNull(); fail(); } catch (IllegalStateException expected) { } } public void testNullLiteralIsNotAString() throws IOException { JsonReader reader = new JsonReader(reader("[null]")); reader.beginArray(); try { reader.nextString(); fail(); } catch (IllegalStateException expected) { } } public void testStrictNameValueSeparator() throws IOException { JsonReader reader = new JsonReader(reader("{\"a\"=true}")); reader.beginObject(); assertEquals("a", reader.nextName()); try { reader.nextBoolean(); fail(); } catch (IOException expected) { } reader = new JsonReader(reader("{\"a\"=>true}")); reader.beginObject(); assertEquals("a", reader.nextName()); try { reader.nextBoolean(); fail(); } catch (IOException expected) { } } public void testLenientNameValueSeparator() throws IOException { JsonReader reader = new JsonReader(reader("{\"a\"=true}")); reader.setLenient(true); reader.beginObject(); assertEquals("a", reader.nextName()); assertEquals(true, reader.nextBoolean()); reader = new JsonReader(reader("{\"a\"=>true}")); reader.setLenient(true); reader.beginObject(); assertEquals("a", reader.nextName()); assertEquals(true, reader.nextBoolean()); } public void testStrictNameValueSeparatorWithSkipValue() throws IOException { JsonReader reader = new JsonReader(reader("{\"a\"=true}")); reader.beginObject(); assertEquals("a", reader.nextName()); try { reader.skipValue(); fail(); } catch (IOException expected) { } reader = new JsonReader(reader("{\"a\"=>true}")); reader.beginObject(); assertEquals("a", reader.nextName()); try { reader.skipValue(); fail(); } catch (IOException expected) { } } public void testCommentsInStringValue() throws Exception { JsonReader reader = new JsonReader(reader("[\"// comment\"]")); reader.beginArray(); assertEquals("// comment", reader.nextString()); reader.endArray(); reader = new JsonReader(reader("{\"a\":\"#someComment\"}")); reader.beginObject(); assertEquals("a", reader.nextName()); assertEquals("#someComment", reader.nextString()); reader.endObject(); reader = new JsonReader(reader("{\"#//a\":\"#some //Comment\"}")); reader.beginObject(); assertEquals("#//a", reader.nextName()); assertEquals("#some //Comment", reader.nextString()); reader.endObject(); } public void testStrictComments() throws IOException { JsonReader reader = new JsonReader(reader("[// comment \n true]")); reader.beginArray(); try { reader.nextBoolean(); fail(); } catch (IOException expected) { } reader = new JsonReader(reader("[# comment \n true]")); reader.beginArray(); try { reader.nextBoolean(); fail(); } catch (IOException expected) { } reader = new JsonReader(reader("[/* comment */ true]")); reader.beginArray(); try { reader.nextBoolean(); fail(); } catch (IOException expected) { } } public void testLenientComments() throws IOException { JsonReader reader = new JsonReader(reader("[// comment \n true]")); reader.setLenient(true); reader.beginArray(); assertEquals(true, reader.nextBoolean()); reader = new JsonReader(reader("[# comment \n true]")); reader.setLenient(true); reader.beginArray(); assertEquals(true, reader.nextBoolean()); reader = new JsonReader(reader("[/* comment */ true]")); reader.setLenient(true); reader.beginArray(); assertEquals(true, reader.nextBoolean()); } public void testStrictCommentsWithSkipValue() throws IOException { JsonReader reader = new JsonReader(reader("[// comment \n true]")); reader.beginArray(); try { reader.skipValue(); fail(); } catch (IOException expected) { } reader = new JsonReader(reader("[# comment \n true]")); reader.beginArray(); try { reader.skipValue(); fail(); } catch (IOException expected) { } reader = new JsonReader(reader("[/* comment */ true]")); reader.beginArray(); try { reader.skipValue(); fail(); } catch (IOException expected) { } } public void testStrictUnquotedNames() throws IOException { JsonReader reader = new JsonReader(reader("{a:true}")); reader.beginObject(); try { reader.nextName(); fail(); } catch (IOException expected) { } } public void testLenientUnquotedNames() throws IOException { JsonReader reader = new JsonReader(reader("{a:true}")); reader.setLenient(true); reader.beginObject(); assertEquals("a", reader.nextName()); } public void testStrictUnquotedNamesWithSkipValue() throws IOException { JsonReader reader = new JsonReader(reader("{a:true}")); reader.beginObject(); try { reader.skipValue(); fail(); } catch (IOException expected) { } } public void testStrictSingleQuotedNames() throws IOException { JsonReader reader = new JsonReader(reader("{'a':true}")); reader.beginObject(); try { reader.nextName(); fail(); } catch (IOException expected) { } } public void testLenientSingleQuotedNames() throws IOException { JsonReader reader = new JsonReader(reader("{'a':true}")); reader.setLenient(true); reader.beginObject(); assertEquals("a", reader.nextName()); } public void testStrictSingleQuotedNamesWithSkipValue() throws IOException { JsonReader reader = new JsonReader(reader("{'a':true}")); reader.beginObject(); try { reader.skipValue(); fail(); } catch (IOException expected) { } } public void testStrictUnquotedStrings() throws IOException { JsonReader reader = new JsonReader(reader("[a]")); reader.beginArray(); try { reader.nextString(); fail(); } catch (MalformedJsonException expected) { } } public void testStrictUnquotedStringsWithSkipValue() throws IOException { JsonReader reader = new JsonReader(reader("[a]")); reader.beginArray(); try { reader.skipValue(); fail(); } catch (MalformedJsonException expected) { } } public void testLenientUnquotedStrings() throws IOException { JsonReader reader = new JsonReader(reader("[a]")); reader.setLenient(true); reader.beginArray(); assertEquals("a", reader.nextString()); } public void testStrictSingleQuotedStrings() throws IOException { JsonReader reader = new JsonReader(reader("['a']")); reader.beginArray(); try { reader.nextString(); fail(); } catch (IOException expected) { } } public void testLenientSingleQuotedStrings() throws IOException { JsonReader reader = new JsonReader(reader("['a']")); reader.setLenient(true); reader.beginArray(); assertEquals("a", reader.nextString()); } public void testStrictSingleQuotedStringsWithSkipValue() throws IOException { JsonReader reader = new JsonReader(reader("['a']")); reader.beginArray(); try { reader.skipValue(); fail(); } catch (IOException expected) { } } public void testStrictSemicolonDelimitedArray() throws IOException { JsonReader reader = new JsonReader(reader("[true;true]")); reader.beginArray(); try { reader.nextBoolean(); reader.nextBoolean(); fail(); } catch (IOException expected) { } } public void testLenientSemicolonDelimitedArray() throws IOException { JsonReader reader = new JsonReader(reader("[true;true]")); reader.setLenient(true); reader.beginArray(); assertEquals(true, reader.nextBoolean()); assertEquals(true, reader.nextBoolean()); } public void testStrictSemicolonDelimitedArrayWithSkipValue() throws IOException { JsonReader reader = new JsonReader(reader("[true;true]")); reader.beginArray(); try { reader.skipValue(); reader.skipValue(); fail(); } catch (IOException expected) { } } public void testStrictSemicolonDelimitedNameValuePair() throws IOException { JsonReader reader = new JsonReader(reader("{\"a\":true;\"b\":true}")); reader.beginObject(); assertEquals("a", reader.nextName()); try { reader.nextBoolean(); reader.nextName(); fail(); } catch (IOException expected) { } } public void testLenientSemicolonDelimitedNameValuePair() throws IOException { JsonReader reader = new JsonReader(reader("{\"a\":true;\"b\":true}")); reader.setLenient(true); reader.beginObject(); assertEquals("a", reader.nextName()); assertEquals(true, reader.nextBoolean()); assertEquals("b", reader.nextName()); } public void testStrictSemicolonDelimitedNameValuePairWithSkipValue() throws IOException { JsonReader reader = new JsonReader(reader("{\"a\":true;\"b\":true}")); reader.beginObject(); assertEquals("a", reader.nextName()); try { reader.skipValue(); reader.skipValue(); fail(); } catch (IOException expected) { } } public void testStrictUnnecessaryArraySeparators() throws IOException { JsonReader reader = new JsonReader(reader("[true,,true]")); reader.beginArray(); assertEquals(true, reader.nextBoolean()); try { reader.nextNull(); fail(); } catch (IOException expected) { } reader = new JsonReader(reader("[,true]")); reader.beginArray(); try { reader.nextNull(); fail(); } catch (IOException expected) { } reader = new JsonReader(reader("[true,]")); reader.beginArray(); assertEquals(true, reader.nextBoolean()); try { reader.nextNull(); fail(); } catch (IOException expected) { } reader = new JsonReader(reader("[,]")); reader.beginArray(); try { reader.nextNull(); fail(); } catch (IOException expected) { } } public void testLenientUnnecessaryArraySeparators() throws IOException { JsonReader reader = new JsonReader(reader("[true,,true]")); reader.setLenient(true); reader.beginArray(); assertEquals(true, reader.nextBoolean()); reader.nextNull(); assertEquals(true, reader.nextBoolean()); reader.endArray(); reader = new JsonReader(reader("[,true]")); reader.setLenient(true); reader.beginArray(); reader.nextNull(); assertEquals(true, reader.nextBoolean()); reader.endArray(); reader = new JsonReader(reader("[true,]")); reader.setLenient(true); reader.beginArray(); assertEquals(true, reader.nextBoolean()); reader.nextNull(); reader.endArray(); reader = new JsonReader(reader("[,]")); reader.setLenient(true); reader.beginArray(); reader.nextNull(); reader.nextNull(); reader.endArray(); } public void testStrictUnnecessaryArraySeparatorsWithSkipValue() throws IOException { JsonReader reader = new JsonReader(reader("[true,,true]")); reader.beginArray(); assertEquals(true, reader.nextBoolean()); try { reader.skipValue(); fail(); } catch (IOException expected) { } reader = new JsonReader(reader("[,true]")); reader.beginArray(); try { reader.skipValue(); fail(); } catch (IOException expected) { } reader = new JsonReader(reader("[true,]")); reader.beginArray(); assertEquals(true, reader.nextBoolean()); try { reader.skipValue(); fail(); } catch (IOException expected) { } reader = new JsonReader(reader("[,]")); reader.beginArray(); try { reader.skipValue(); fail(); } catch (IOException expected) { } } public void testStrictMultipleTopLevelValues() throws IOException { JsonReader reader = new JsonReader(reader("[] []")); reader.beginArray(); reader.endArray(); try { reader.peek(); fail(); } catch (IOException expected) { } } public void testLenientMultipleTopLevelValues() throws IOException { JsonReader reader = new JsonReader(reader("[] true {}")); reader.setLenient(true); reader.beginArray(); reader.endArray(); assertEquals(true, reader.nextBoolean()); reader.beginObject(); reader.endObject(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testStrictMultipleTopLevelValuesWithSkipValue() throws IOException { JsonReader reader = new JsonReader(reader("[] []")); reader.beginArray(); reader.endArray(); try { reader.skipValue(); fail(); } catch (IOException expected) { } } public void testTopLevelValueTypes() throws IOException { JsonReader reader1 = new JsonReader(reader("true")); assertTrue(reader1.nextBoolean()); assertEquals(JsonToken.END_DOCUMENT, reader1.peek()); JsonReader reader2 = new JsonReader(reader("false")); assertFalse(reader2.nextBoolean()); assertEquals(JsonToken.END_DOCUMENT, reader2.peek()); JsonReader reader3 = new JsonReader(reader("null")); assertEquals(JsonToken.NULL, reader3.peek()); reader3.nextNull(); assertEquals(JsonToken.END_DOCUMENT, reader3.peek()); JsonReader reader4 = new JsonReader(reader("123")); assertEquals(123, reader4.nextInt()); assertEquals(JsonToken.END_DOCUMENT, reader4.peek()); JsonReader reader5 = new JsonReader(reader("123.4")); assertEquals(123.4, reader5.nextDouble()); assertEquals(JsonToken.END_DOCUMENT, reader5.peek()); JsonReader reader6 = new JsonReader(reader("\"a\"")); assertEquals("a", reader6.nextString()); assertEquals(JsonToken.END_DOCUMENT, reader6.peek()); } public void testTopLevelValueTypeWithSkipValue() throws IOException { JsonReader reader = new JsonReader(reader("true")); reader.skipValue(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testStrictNonExecutePrefix() { JsonReader reader = new JsonReader(reader(")]}'\n []")); try { reader.beginArray(); fail(); } catch (IOException expected) { } } public void testStrictNonExecutePrefixWithSkipValue() { JsonReader reader = new JsonReader(reader(")]}'\n []")); try { reader.skipValue(); fail(); } catch (IOException expected) { } } public void testLenientNonExecutePrefix() throws IOException { JsonReader reader = new JsonReader(reader(")]}'\n []")); reader.setLenient(true); reader.beginArray(); reader.endArray(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testLenientNonExecutePrefixWithLeadingWhitespace() throws IOException { JsonReader reader = new JsonReader(reader("\r\n \t)]}'\n []")); reader.setLenient(true); reader.beginArray(); reader.endArray(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testLenientPartialNonExecutePrefix() { JsonReader reader = new JsonReader(reader(")]}' []")); reader.setLenient(true); try { assertEquals(")", reader.nextString()); reader.nextString(); fail(); } catch (IOException expected) { } } public void testBomIgnoredAsFirstCharacterOfDocument() throws IOException { JsonReader reader = new JsonReader(reader("\ufeff[]")); reader.beginArray(); reader.endArray(); } public void testBomForbiddenAsOtherCharacterInDocument() throws IOException { JsonReader reader = new JsonReader(reader("[\ufeff]")); reader.beginArray(); try { reader.endArray(); fail(); } catch (IOException expected) { } } public void testFailWithPosition() throws IOException { testFailWithPosition("Expected value at line 6 column 5 path $[1]", "[\n\n\n\n\n\"a\",}]"); } public void testFailWithPositionGreaterThanBufferSize() throws IOException { String spaces = repeat(' ', 8192); testFailWithPosition("Expected value at line 6 column 5 path $[1]", "[\n\n" + spaces + "\n\n\n\"a\",}]"); } public void testFailWithPositionOverSlashSlashEndOfLineComment() throws IOException { testFailWithPosition("Expected value at line 5 column 6 path $[1]", "\n// foo\n\n//bar\r\n[\"a\",}"); } public void testFailWithPositionOverHashEndOfLineComment() throws IOException { testFailWithPosition("Expected value at line 5 column 6 path $[1]", "\n# foo\n\n#bar\r\n[\"a\",}"); } public void testFailWithPositionOverCStyleComment() throws IOException { testFailWithPosition("Expected value at line 6 column 12 path $[1]", "\n\n/* foo\n*\n*\r\nbar */[\"a\",}"); } public void testFailWithPositionOverQuotedString() throws IOException { testFailWithPosition("Expected value at line 5 column 3 path $[1]", "[\"foo\nbar\r\nbaz\n\",\n }"); } public void testFailWithPositionOverUnquotedString() throws IOException { testFailWithPosition("Expected value at line 5 column 2 path $[1]", "[\n\nabcd\n\n,}"); } public void testFailWithEscapedNewlineCharacter() throws IOException { testFailWithPosition("Expected value at line 5 column 3 path $[1]", "[\n\n\"\\\n\n\",}"); } public void testFailWithPositionIsOffsetByBom() throws IOException { testFailWithPosition("Expected value at line 1 column 6 path $[1]", "\ufeff[\"a\",}]"); } private void testFailWithPosition(String message, String json) throws IOException { // Validate that it works reading the string normally. JsonReader reader1 = new JsonReader(reader(json)); reader1.setLenient(true); reader1.beginArray(); reader1.nextString(); try { reader1.peek(); fail(); } catch (IOException expected) { assertEquals(message, expected.getMessage()); } // Also validate that it works when skipping. JsonReader reader2 = new JsonReader(reader(json)); reader2.setLenient(true); reader2.beginArray(); reader2.skipValue(); try { reader2.peek(); fail(); } catch (IOException expected) { assertEquals(message, expected.getMessage()); } } public void testFailWithPositionDeepPath() throws IOException { JsonReader reader = new JsonReader(reader("[1,{\"a\":[2,3,}")); reader.beginArray(); reader.nextInt(); reader.beginObject(); reader.nextName(); reader.beginArray(); reader.nextInt(); reader.nextInt(); try { reader.peek(); fail(); } catch (IOException expected) { assertEquals("Expected value at line 1 column 14 path $[1].a[2]", expected.getMessage()); } } public void testStrictVeryLongNumber() throws IOException { JsonReader reader = new JsonReader(reader("[0." + repeat('9', 8192) + "]")); reader.beginArray(); try { assertEquals(1d, reader.nextDouble()); fail(); } catch (MalformedJsonException expected) { } } public void testLenientVeryLongNumber() throws IOException { JsonReader reader = new JsonReader(reader("[0." + repeat('9', 8192) + "]")); reader.setLenient(true); reader.beginArray(); assertEquals(JsonToken.STRING, reader.peek()); assertEquals(1d, reader.nextDouble()); reader.endArray(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testVeryLongUnquotedLiteral() throws IOException { String literal = "a" + repeat('b', 8192) + "c"; JsonReader reader = new JsonReader(reader("[" + literal + "]")); reader.setLenient(true); reader.beginArray(); assertEquals(literal, reader.nextString()); reader.endArray(); } public void testDeeplyNestedArrays() throws IOException { // this is nested 40 levels deep; Gson is tuned for nesting is 30 levels deep or fewer JsonReader reader = new JsonReader(reader( "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]")); for (int i = 0; i < 40; i++) { reader.beginArray(); } assertEquals("$[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0]" + "[0][0][0][0][0][0][0][0][0][0][0][0][0][0]", reader.getPath()); for (int i = 0; i < 40; i++) { reader.endArray(); } assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testDeeplyNestedObjects() throws IOException { // Build a JSON document structured like {"a":{"a":{"a":{"a":true}}}}, but 40 levels deep String array = "{\"a\":%s}"; String json = "true"; for (int i = 0; i < 40; i++) { json = String.format(array, json); } JsonReader reader = new JsonReader(reader(json)); for (int i = 0; i < 40; i++) { reader.beginObject(); assertEquals("a", reader.nextName()); } assertEquals("$.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a" + ".a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", reader.getPath()); assertEquals(true, reader.nextBoolean()); for (int i = 0; i < 40; i++) { reader.endObject(); } assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } // http://code.google.com/p/google-gson/issues/detail?id=409 public void testStringEndingInSlash() throws IOException { JsonReader reader = new JsonReader(reader("/")); reader.setLenient(true); try { reader.peek(); fail(); } catch (MalformedJsonException expected) { } } public void testDocumentWithCommentEndingInSlash() throws IOException { JsonReader reader = new JsonReader(reader("/* foo *//")); reader.setLenient(true); try { reader.peek(); fail(); } catch (MalformedJsonException expected) { } } public void testStringWithLeadingSlash() throws IOException { JsonReader reader = new JsonReader(reader("/x")); reader.setLenient(true); try { reader.peek(); fail(); } catch (MalformedJsonException expected) { } } public void testUnterminatedObject() throws IOException { JsonReader reader = new JsonReader(reader("{\"a\":\"android\"x")); reader.setLenient(true); reader.beginObject(); assertEquals("a", reader.nextName()); assertEquals("android", reader.nextString()); try { reader.peek(); fail(); } catch (MalformedJsonException expected) { } } public void testVeryLongQuotedString() throws IOException { char[] stringChars = new char[1024 * 16]; Arrays.fill(stringChars, 'x'); String string = new String(stringChars); String json = "[\"" + string + "\"]"; JsonReader reader = new JsonReader(reader(json)); reader.beginArray(); assertEquals(string, reader.nextString()); reader.endArray(); } public void testVeryLongUnquotedString() throws IOException { char[] stringChars = new char[1024 * 16]; Arrays.fill(stringChars, 'x'); String string = new String(stringChars); String json = "[" + string + "]"; JsonReader reader = new JsonReader(reader(json)); reader.setLenient(true); reader.beginArray(); assertEquals(string, reader.nextString()); reader.endArray(); } public void testVeryLongUnterminatedString() throws IOException { char[] stringChars = new char[1024 * 16]; Arrays.fill(stringChars, 'x'); String string = new String(stringChars); String json = "[" + string; JsonReader reader = new JsonReader(reader(json)); reader.setLenient(true); reader.beginArray(); assertEquals(string, reader.nextString()); try { reader.peek(); fail(); } catch (EOFException expected) { } } public void testSkipVeryLongUnquotedString() throws IOException { JsonReader reader = new JsonReader(reader("[" + repeat('x', 8192) + "]")); reader.setLenient(true); reader.beginArray(); reader.skipValue(); reader.endArray(); } public void testSkipTopLevelUnquotedString() throws IOException { JsonReader reader = new JsonReader(reader(repeat('x', 8192))); reader.setLenient(true); reader.skipValue(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testSkipVeryLongQuotedString() throws IOException { JsonReader reader = new JsonReader(reader("[\"" + repeat('x', 8192) + "\"]")); reader.beginArray(); reader.skipValue(); reader.endArray(); } public void testSkipTopLevelQuotedString() throws IOException { JsonReader reader = new JsonReader(reader("\"" + repeat('x', 8192) + "\"")); reader.setLenient(true); reader.skipValue(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testStringAsNumberWithTruncatedExponent() throws IOException { JsonReader reader = new JsonReader(reader("[123e]")); reader.setLenient(true); reader.beginArray(); assertEquals(STRING, reader.peek()); } public void testStringAsNumberWithDigitAndNonDigitExponent() throws IOException { JsonReader reader = new JsonReader(reader("[123e4b]")); reader.setLenient(true); reader.beginArray(); assertEquals(STRING, reader.peek()); } public void testStringAsNumberWithNonDigitExponent() throws IOException { JsonReader reader = new JsonReader(reader("[123eb]")); reader.setLenient(true); reader.beginArray(); assertEquals(STRING, reader.peek()); } public void testEmptyStringName() throws IOException { JsonReader reader = new JsonReader(reader("{\"\":true}")); reader.setLenient(true); assertEquals(BEGIN_OBJECT, reader.peek()); reader.beginObject(); assertEquals(NAME, reader.peek()); assertEquals("", reader.nextName()); assertEquals(JsonToken.BOOLEAN, reader.peek()); assertEquals(true, reader.nextBoolean()); assertEquals(JsonToken.END_OBJECT, reader.peek()); reader.endObject(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testStrictExtraCommasInMaps() throws IOException { JsonReader reader = new JsonReader(reader("{\"a\":\"b\",}")); reader.beginObject(); assertEquals("a", reader.nextName()); assertEquals("b", reader.nextString()); try { reader.peek(); fail(); } catch (IOException expected) { } } public void testLenientExtraCommasInMaps() throws IOException { JsonReader reader = new JsonReader(reader("{\"a\":\"b\",}")); reader.setLenient(true); reader.beginObject(); assertEquals("a", reader.nextName()); assertEquals("b", reader.nextString()); try { reader.peek(); fail(); } catch (IOException expected) { } } private String repeat(char c, int count) { char[] array = new char[count]; Arrays.fill(array, c); return new String(array); } public void testMalformedDocuments() throws IOException { assertDocument("{]", BEGIN_OBJECT, IOException.class); assertDocument("{,", BEGIN_OBJECT, IOException.class); assertDocument("{{", BEGIN_OBJECT, IOException.class); assertDocument("{[", BEGIN_OBJECT, IOException.class); assertDocument("{:", BEGIN_OBJECT, IOException.class); assertDocument("{\"name\",", BEGIN_OBJECT, NAME, IOException.class); assertDocument("{\"name\",", BEGIN_OBJECT, NAME, IOException.class); assertDocument("{\"name\":}", BEGIN_OBJECT, NAME, IOException.class); assertDocument("{\"name\"::", BEGIN_OBJECT, NAME, IOException.class); assertDocument("{\"name\":,", BEGIN_OBJECT, NAME, IOException.class); assertDocument("{\"name\"=}", BEGIN_OBJECT, NAME, IOException.class); assertDocument("{\"name\"=>}", BEGIN_OBJECT, NAME, IOException.class); assertDocument("{\"name\"=>\"string\":", BEGIN_OBJECT, NAME, STRING, IOException.class); assertDocument("{\"name\"=>\"string\"=", BEGIN_OBJECT, NAME, STRING, IOException.class); assertDocument("{\"name\"=>\"string\"=>", BEGIN_OBJECT, NAME, STRING, IOException.class); assertDocument("{\"name\"=>\"string\",", BEGIN_OBJECT, NAME, STRING, IOException.class); assertDocument("{\"name\"=>\"string\",\"name\"", BEGIN_OBJECT, NAME, STRING, NAME); assertDocument("[}", BEGIN_ARRAY, IOException.class); assertDocument("[,]", BEGIN_ARRAY, NULL, NULL, END_ARRAY); assertDocument("{", BEGIN_OBJECT, IOException.class); assertDocument("{\"name\"", BEGIN_OBJECT, NAME, IOException.class); assertDocument("{\"name\",", BEGIN_OBJECT, NAME, IOException.class); assertDocument("{'name'", BEGIN_OBJECT, NAME, IOException.class); assertDocument("{'name',", BEGIN_OBJECT, NAME, IOException.class); assertDocument("{name", BEGIN_OBJECT, NAME, IOException.class); assertDocument("[", BEGIN_ARRAY, IOException.class); assertDocument("[string", BEGIN_ARRAY, STRING, IOException.class); assertDocument("[\"string\"", BEGIN_ARRAY, STRING, IOException.class); assertDocument("['string'", BEGIN_ARRAY, STRING, IOException.class); assertDocument("[123", BEGIN_ARRAY, NUMBER, IOException.class); assertDocument("[123,", BEGIN_ARRAY, NUMBER, IOException.class); assertDocument("{\"name\":123", BEGIN_OBJECT, NAME, NUMBER, IOException.class); assertDocument("{\"name\":123,", BEGIN_OBJECT, NAME, NUMBER, IOException.class); assertDocument("{\"name\":\"string\"", BEGIN_OBJECT, NAME, STRING, IOException.class); assertDocument("{\"name\":\"string\",", BEGIN_OBJECT, NAME, STRING, IOException.class); assertDocument("{\"name\":'string'", BEGIN_OBJECT, NAME, STRING, IOException.class); assertDocument("{\"name\":'string',", BEGIN_OBJECT, NAME, STRING, IOException.class); assertDocument("{\"name\":false", BEGIN_OBJECT, NAME, BOOLEAN, IOException.class); assertDocument("{\"name\":false,,", BEGIN_OBJECT, NAME, BOOLEAN, IOException.class); } /** * This test behave slightly differently in Gson 2.2 and earlier. It fails * during peek rather than during nextString(). */ public void testUnterminatedStringFailure() throws IOException { JsonReader reader = new JsonReader(reader("[\"string")); reader.setLenient(true); reader.beginArray(); assertEquals(JsonToken.STRING, reader.peek()); try { reader.nextString(); fail(); } catch (MalformedJsonException expected) { } } private void assertDocument(String document, Object... expectations) throws IOException { JsonReader reader = new JsonReader(reader(document)); reader.setLenient(true); for (Object expectation : expectations) { if (expectation == BEGIN_OBJECT) { reader.beginObject(); } else if (expectation == BEGIN_ARRAY) { reader.beginArray(); } else if (expectation == END_OBJECT) { reader.endObject(); } else if (expectation == END_ARRAY) { reader.endArray(); } else if (expectation == NAME) { assertEquals("name", reader.nextName()); } else if (expectation == BOOLEAN) { assertEquals(false, reader.nextBoolean()); } else if (expectation == STRING) { assertEquals("string", reader.nextString()); } else if (expectation == NUMBER) { assertEquals(123, reader.nextInt()); } else if (expectation == NULL) { reader.nextNull(); } else if (expectation == IOException.class) { try { reader.peek(); fail(); } catch (IOException expected) { } } else { throw new AssertionError(); } } } /** * Returns a reader that returns one character at a time. */ private Reader reader(final String s) { /* if (true) */ return new StringReader(s); /* return new Reader() { int position = 0; @Override public int read(char[] buffer, int offset, int count) throws IOException { if (position == s.length()) { return -1; } else if (count > 0) { buffer[offset] = s.charAt(position++); return 1; } else { throw new IllegalArgumentException(); } } @Override public void close() throws IOException { } }; */ } }