diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java index 8910cbc46a..96929e6fec 100644 --- a/gson/src/main/java/com/google/gson/Gson.java +++ b/gson/src/main/java/com/google/gson/Gson.java @@ -102,7 +102,7 @@ */ public final class Gson { static final boolean DEFAULT_JSON_NON_EXECUTABLE = false; - static final boolean DEFAULT_LENIENT = false; + static final boolean DEFAULT_LENIENT = true; static final boolean DEFAULT_PRETTY_PRINT = false; static final boolean DEFAULT_ESCAPE_HTML = true; static final boolean DEFAULT_SERIALIZE_NULLS = false; @@ -847,15 +847,15 @@ private static void assertFullConsumption(Object obj, JsonReader reader) { * Reads the next JSON value from {@code reader} and convert it to an object * of type {@code typeOfT}. Returns {@code null}, if the {@code reader} is at EOF. * Since Type is not parameterized by T, this method is type unsafe and should be used carefully - * + *

+ * The leniency of the reader passed in is respected. See {@linkplain JsonReader#setLenient(boolean)} + *

* @throws JsonIOException if there was a problem writing to the Reader * @throws JsonSyntaxException if json is not a valid representation for an object of type */ @SuppressWarnings("unchecked") public T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException { boolean isEmpty = true; - boolean oldLenient = reader.isLenient(); - reader.setLenient(true); try { reader.peek(); isEmpty = false; @@ -877,8 +877,6 @@ public T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, J } catch (IOException e) { // TODO(inder): Figure out whether it is indeed right to rethrow this as JsonSyntaxException throw new JsonSyntaxException(e); - } finally { - reader.setLenient(oldLenient); } } diff --git a/gson/src/main/java/com/google/gson/GsonBuilder.java b/gson/src/main/java/com/google/gson/GsonBuilder.java index 0c917d46fa..c964f52e30 100644 --- a/gson/src/main/java/com/google/gson/GsonBuilder.java +++ b/gson/src/main/java/com/google/gson/GsonBuilder.java @@ -363,13 +363,23 @@ public GsonBuilder setPrettyPrinting() { } /** - * By default, Gson is strict and only accepts JSON as specified by - * RFC 4627. This option makes the parser - * liberal in what it accepts. + * By default, Gson is liberal in what it accepts. Setting lenient to false causes Gson to + * only accept JSON as specified by + * RFC 4627. * * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern * @see JsonReader#setLenient(boolean) */ + public GsonBuilder setLenient(boolean lenient) { + this.lenient = lenient; + return this; + } + + /** + * Gson is lenient by default. Use {@link #setLenient(boolean)} if + * you wish to change the leniency + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + */ public GsonBuilder setLenient() { lenient = true; return this; diff --git a/gson/src/test/java/com/google/gson/functional/LeniencyTest.java b/gson/src/test/java/com/google/gson/functional/LeniencyTest.java index 6b5375e4b0..7fb714e83d 100644 --- a/gson/src/test/java/com/google/gson/functional/LeniencyTest.java +++ b/gson/src/test/java/com/google/gson/functional/LeniencyTest.java @@ -17,30 +17,91 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonSyntaxException; import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; + import java.util.List; import junit.framework.TestCase; import static java.util.Collections.singletonList; +import java.io.StringReader; +import java.lang.reflect.Type; + /** * Functional tests for leniency option. */ public class LeniencyTest extends TestCase { - private Gson gson; + private Gson lenientGson; + private Gson strictGson; @Override protected void setUp() throws Exception { super.setUp(); - gson = new GsonBuilder().setLenient().create(); + lenientGson = new GsonBuilder().create(); + strictGson = new GsonBuilder().setLenient(false).create(); } public void testLenientFromJson() { - List json = gson.fromJson("" + final String testString = "" + + "[ # One!\n" + + " 'Hi' #Element!\n" + + "] # Array!"; + final String expectedResult = "Hi"; + Type type = new TypeToken>() {}.getType(); + + JsonReader reader = new JsonReader(new StringReader(testString)); + reader.setLenient(true); + // fromJson(JsonReader, Type) should respect the leniency of + // the JsonReader + List json = strictGson.fromJson(reader, type); + assertEquals(singletonList(expectedResult), json); + + // the factory method should set the leniency of the created factory + // to be the same as the leniency of the Gson instance + reader = lenientGson.newJsonReader(new StringReader(testString)); + assertTrue(reader.isLenient()); + // fromJson(JsonReader, Type) should respect the leniency of + // the JsonReader + json = strictGson.fromJson(reader, type); + assertEquals(singletonList(expectedResult), json); + + json = lenientGson.fromJson(testString, type); + assertEquals(singletonList(expectedResult), json); + } + + public void testStrictFromJson() { + final String testString = "" + "[ # One!\n" + " 'Hi' #Element!\n" - + "] # Array!", new TypeToken>() {}.getType()); - assertEquals(singletonList("Hi"), json); + + "]"; + Type type = new TypeToken>(){}.getType(); + + try { + // JsonReader is strict by default + JsonReader reader = new JsonReader(new StringReader(testString)); + // fromJson(JsonReader, Type) should respect the leniency of + // the JsonReader + lenientGson.fromJson(reader, type); + fail(); + } catch (JsonSyntaxException expected) { } + + try { + // the factory method should set the leniency of the created factory + // to be the same as the leniency of the Gson instance + JsonReader reader = strictGson.newJsonReader(new StringReader(testString)); + assertFalse(reader.isLenient()); + // fromJson(JsonReader, Type) should respect the leniency of + // the JsonReader + lenientGson.fromJson(reader, type); + fail(); + } catch(JsonSyntaxException expected) { } + + try { + strictGson.fromJson(testString, type); + fail(); + } catch (JsonSyntaxException expected) { } } } diff --git a/gson/src/test/java/com/google/gson/functional/PrimitiveTest.java b/gson/src/test/java/com/google/gson/functional/PrimitiveTest.java index bb28ed1ec5..6f0f866ab6 100644 --- a/gson/src/test/java/com/google/gson/functional/PrimitiveTest.java +++ b/gson/src/test/java/com/google/gson/functional/PrimitiveTest.java @@ -18,6 +18,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonIOException; import com.google.gson.JsonPrimitive; import com.google.gson.JsonSyntaxException; import com.google.gson.LongSerializationPolicy; @@ -556,7 +557,7 @@ public void testUnquotedStringDeserializationFails() throws Exception { try { gson.fromJson(value, String.class); fail(); - } catch (JsonSyntaxException expected) { } + } catch (JsonIOException expected) { } } public void testHtmlCharacterSerialization() throws Exception {