From 103edb9c36988c42170a75046eee37407c0c6475 Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Mon, 8 Nov 2010 19:16:05 +0000 Subject: [PATCH] Don't return null on an unexpected EOF unless the document is empty. This brings us back to compatibility with GSON 1.5. --- .../main/java/com/google/gson/Streams.java | 88 +++++++++++-------- .../google/gson/functional/ObjectTest.java | 10 +++ 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/gson/src/main/java/com/google/gson/Streams.java b/gson/src/main/java/com/google/gson/Streams.java index c1c54dab..fec5301e 100644 --- a/gson/src/main/java/com/google/gson/Streams.java +++ b/gson/src/main/java/com/google/gson/Streams.java @@ -17,9 +17,8 @@ package com.google.gson; import com.google.gson.stream.JsonReader; -import com.google.gson.stream.MalformedJsonException; import com.google.gson.stream.JsonWriter; - +import com.google.gson.stream.MalformedJsonException; import java.io.EOFException; import java.io.IOException; import java.io.Writer; @@ -34,43 +33,21 @@ final class Streams { * Takes a reader in any state and returns the next value as a JsonElement. */ static JsonElement parse(JsonReader reader) throws JsonParseException { + boolean isEmpty = true; try { - switch (reader.peek()) { - case STRING: - return new JsonPrimitive(reader.nextString()); - case NUMBER: - String number = reader.nextString(); - return new JsonPrimitive(JsonPrimitive.stringToNumber(number)); - case BOOLEAN: - return new JsonPrimitive(reader.nextBoolean()); - case NULL: - reader.nextNull(); - return JsonNull.createJsonNull(); - case BEGIN_ARRAY: - JsonArray array = new JsonArray(); - reader.beginArray(); - while (reader.hasNext()) { - array.add(parse(reader)); - } - reader.endArray(); - return array; - case BEGIN_OBJECT: - JsonObject object = new JsonObject(); - reader.beginObject(); - while (reader.hasNext()) { - object.add(reader.nextName(), parse(reader)); - } - reader.endObject(); - return object; - case END_DOCUMENT: - case NAME: - case END_OBJECT: - case END_ARRAY: - default: - throw new IllegalArgumentException(); - } + reader.peek(); + isEmpty = false; + return parseRecursive(reader); } catch (EOFException e) { - return JsonNull.createJsonNull(); + /* + * For compatibility with JSON 1.5 and earlier, we return a JsonNull for + * empty documents instead of throwing. + */ + if (isEmpty) { + return JsonNull.createJsonNull(); + } else { + throw new JsonIOException(e); + } } catch (MalformedJsonException e) { throw new JsonSyntaxException(e); } catch (IOException e) { @@ -80,6 +57,43 @@ final class Streams { } } + private static JsonElement parseRecursive(JsonReader reader) throws IOException { + switch (reader.peek()) { + case STRING: + return new JsonPrimitive(reader.nextString()); + case NUMBER: + String number = reader.nextString(); + return new JsonPrimitive(JsonPrimitive.stringToNumber(number)); + case BOOLEAN: + return new JsonPrimitive(reader.nextBoolean()); + case NULL: + reader.nextNull(); + return JsonNull.createJsonNull(); + case BEGIN_ARRAY: + JsonArray array = new JsonArray(); + reader.beginArray(); + while (reader.hasNext()) { + array.add(parseRecursive(reader)); + } + reader.endArray(); + return array; + case BEGIN_OBJECT: + JsonObject object = new JsonObject(); + reader.beginObject(); + while (reader.hasNext()) { + object.add(reader.nextName(), parseRecursive(reader)); + } + reader.endObject(); + return object; + case END_DOCUMENT: + case NAME: + case END_OBJECT: + case END_ARRAY: + default: + throw new IllegalArgumentException(); + } + } + /** * Writes the JSON element to the writer, recursively. */ diff --git a/gson/src/test/java/com/google/gson/functional/ObjectTest.java b/gson/src/test/java/com/google/gson/functional/ObjectTest.java index 8e48492f..4f806242 100644 --- a/gson/src/test/java/com/google/gson/functional/ObjectTest.java +++ b/gson/src/test/java/com/google/gson/functional/ObjectTest.java @@ -20,6 +20,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.InstanceCreator; import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; import com.google.gson.common.TestTypes.ArrayOfObjects; import com.google.gson.common.TestTypes.BagOfPrimitiveWrappers; import com.google.gson.common.TestTypes.BagOfPrimitives; @@ -30,6 +31,7 @@ import com.google.gson.common.TestTypes.ClassWithTransientFields; import com.google.gson.common.TestTypes.Nested; import com.google.gson.common.TestTypes.PrimitiveArray; +import com.google.gson.reflect.TypeToken; import java.util.List; import junit.framework.TestCase; @@ -145,6 +147,14 @@ public class ObjectTest extends TestCase { assertNull(object); } + public void testTruncatedDeserialization() { + try { + gson.fromJson("[\"a\", \"b\",", new TypeToken>() {}.getType()); + fail(); + } catch (JsonParseException expected) { + } + } + public void testNullDeserialization() throws Exception { String myNullObject = null; Object object = gson.fromJson(myNullObject, Object.class);