Skip to content

Commit fbde6d2

Browse files
committed
feat: GsonFactory to have read leniency option
1 parent 0664e17 commit fbde6d2

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

google-http-client-gson/src/main/java/com/google/api/client/json/gson/GsonFactory.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ public static GsonFactory getDefaultInstance() {
5252
return InstanceHolder.INSTANCE;
5353
}
5454

55+
private boolean readLeniency = false;
56+
5557
/** Holder for the result of {@link #getDefaultInstance()}. */
5658
@Beta
5759
static class InstanceHolder {
@@ -90,4 +92,16 @@ public JsonGenerator createJsonGenerator(OutputStream out, Charset enc) {
9092
public JsonGenerator createJsonGenerator(Writer writer) {
9193
return new GsonGenerator(this, new JsonWriter(writer));
9294
}
95+
96+
/** Returns true if it gives leniency to reading JSON value. */
97+
boolean getReadLeniency() {
98+
return readLeniency;
99+
}
100+
101+
/** Returns copy of GsonFactory instance that is lenient when reading JSON value. */
102+
public GsonFactory withReadLeniency() {
103+
GsonFactory copy = new GsonFactory();
104+
copy.readLeniency = true;
105+
return copy;
106+
}
93107
}

google-http-client-gson/src/main/java/com/google/api/client/json/gson/GsonParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class GsonParser extends JsonParser {
4343
GsonParser(GsonFactory factory, JsonReader reader) {
4444
this.factory = factory;
4545
this.reader = reader;
46-
reader.setLenient(false);
46+
reader.setLenient(factory.getReadLeniency());
4747
}
4848

4949
@Override

google-http-client-gson/src/test/java/com/google/api/client/json/gson/GsonFactoryTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,16 @@
1414

1515
package com.google.api.client.json.gson;
1616

17+
import com.google.api.client.json.GenericJson;
1718
import com.google.api.client.json.JsonFactory;
19+
import com.google.api.client.json.JsonObjectParser;
1820
import com.google.api.client.json.JsonParser;
1921
import com.google.api.client.test.json.AbstractJsonFactoryTest;
22+
import com.google.gson.stream.MalformedJsonException;
23+
import java.io.ByteArrayInputStream;
2024
import java.io.IOException;
25+
import java.io.InputStream;
26+
import java.nio.charset.StandardCharsets;
2127
import java.util.ArrayList;
2228

2329
/**
@@ -94,4 +100,30 @@ public final void testGetByteValue() throws IOException {
94100
assertNotNull(ex.getMessage());
95101
}
96102
}
103+
104+
public final void testReaderLeniency_lenient() throws IOException {
105+
JsonObjectParser parser =
106+
new JsonObjectParser(GsonFactory.getDefaultInstance().withReadLeniency());
107+
108+
// This prefix in JSON body is used to prevent Cross-site script inclusion (XSSI).
109+
InputStream inputStream =
110+
new ByteArrayInputStream((")]}'\n" + JSON_ENTRY_PRETTY).getBytes(StandardCharsets.UTF_8));
111+
GenericJson json = parser.parseAndClose(inputStream, StandardCharsets.UTF_8, GenericJson.class);
112+
113+
assertEquals("foo", json.get("title"));
114+
}
115+
116+
public final void testReaderLeniency_not_lenient() throws IOException {
117+
JsonObjectParser parser = new JsonObjectParser(GsonFactory.getDefaultInstance());
118+
119+
try {
120+
// This prefix in JSON body is used to prevent Cross-site script inclusion (XSSI).
121+
InputStream inputStream =
122+
new ByteArrayInputStream((")]}'\n" + JSON_ENTRY_PRETTY).getBytes(StandardCharsets.UTF_8));
123+
parser.parseAndClose(inputStream, StandardCharsets.UTF_8, GenericJson.class);
124+
fail("The read leniency should fail the malformed JSON input.");
125+
} catch (MalformedJsonException ex) {
126+
assertNotNull(ex.getMessage());
127+
}
128+
}
97129
}

0 commit comments

Comments
 (0)