Skip to content

Commit

Permalink
Gson respects the lenient flag
Browse files Browse the repository at this point in the history
  • Loading branch information
sgbrown committed Mar 29, 2016
1 parent 0c7e399 commit 4b9a7ac
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 15 deletions.
10 changes: 4 additions & 6 deletions gson/src/main/java/com/google/gson/Gson.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
*
* <p>
* The leniency of the reader passed in is respected. See {@linkplain JsonReader#setLenient(boolean)}
* </p>
* @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> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
boolean isEmpty = true;
boolean oldLenient = reader.isLenient();
reader.setLenient(true);
try {
reader.peek();
isEmpty = false;
Expand All @@ -877,8 +877,6 @@ public <T> 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);
}
}

Expand Down
16 changes: 13 additions & 3 deletions gson/src/main/java/com/google/gson/GsonBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -363,13 +363,23 @@ public GsonBuilder setPrettyPrinting() {
}

/**
* By default, Gson is strict and only accepts JSON as specified by
* <a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>. 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
* <a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>.
*
* @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;
Expand Down
71 changes: 66 additions & 5 deletions gson/src/test/java/com/google/gson/functional/LeniencyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> json = gson.fromJson(""
final String testString = ""
+ "[ # One!\n"
+ " 'Hi' #Element!\n"
+ "] # Array!";
final String expectedResult = "Hi";
Type type = new TypeToken<List<String>>() {}.getType();

JsonReader reader = new JsonReader(new StringReader(testString));
reader.setLenient(true);
// fromJson(JsonReader, Type) should respect the leniency of
// the JsonReader
List<String> 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<List<String>>() {}.getType());
assertEquals(singletonList("Hi"), json);
+ "]";
Type type = new TypeToken<List<String>>(){}.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) { }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 4b9a7ac

Please sign in to comment.