Skip to content

Commit 0a505a7

Browse files
authored
fix: GSON parser now throws IOException on invalid JSON input (#1355)
Previously, the `GsonParser` class threw an `IllegalArgument` (unchecked) exception. This does not change the interface for `JsonParser` which already declares `throws IOException`
1 parent 4d85543 commit 0a505a7

File tree

6 files changed

+69
-39
lines changed

6 files changed

+69
-39
lines changed

google-http-client-gson/pom.xml

-5
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,5 @@
8181
<groupId>com.google.code.gson</groupId>
8282
<artifactId>gson</artifactId>
8383
</dependency>
84-
<dependency>
85-
<groupId>com.google.guava</groupId>
86-
<artifactId>guava</artifactId>
87-
<scope>test</scope>
88-
</dependency>
8984
</dependencies>
9085
</project>

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

+14-14
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import com.google.api.client.json.JsonFactory;
1818
import com.google.api.client.json.JsonParser;
1919
import com.google.api.client.json.JsonToken;
20-
import com.google.api.client.util.Preconditions;
2120
import com.google.gson.stream.JsonReader;
2221
import java.io.EOFException;
2322
import java.io.IOException;
@@ -44,8 +43,7 @@ class GsonParser extends JsonParser {
4443
GsonParser(GsonFactory factory, JsonReader reader) {
4544
this.factory = factory;
4645
this.reader = reader;
47-
// lenient to allow top-level values of any type
48-
reader.setLenient(true);
46+
reader.setLenient(false);
4947
}
5048

5149
@Override
@@ -69,56 +67,58 @@ public JsonFactory getFactory() {
6967
}
7068

7169
@Override
72-
public byte getByteValue() {
70+
public byte getByteValue() throws IOException {
7371
checkNumber();
7472
return Byte.parseByte(currentText);
7573
}
7674

7775
@Override
78-
public short getShortValue() {
76+
public short getShortValue() throws IOException {
7977
checkNumber();
8078
return Short.parseShort(currentText);
8179
}
8280

8381
@Override
84-
public int getIntValue() {
82+
public int getIntValue() throws IOException {
8583
checkNumber();
8684
return Integer.parseInt(currentText);
8785
}
8886

8987
@Override
90-
public float getFloatValue() {
88+
public float getFloatValue() throws IOException {
9189
checkNumber();
9290
return Float.parseFloat(currentText);
9391
}
9492

9593
@Override
96-
public BigInteger getBigIntegerValue() {
94+
public BigInteger getBigIntegerValue() throws IOException {
9795
checkNumber();
9896
return new BigInteger(currentText);
9997
}
10098

10199
@Override
102-
public BigDecimal getDecimalValue() {
100+
public BigDecimal getDecimalValue() throws IOException {
103101
checkNumber();
104102
return new BigDecimal(currentText);
105103
}
106104

107105
@Override
108-
public double getDoubleValue() {
106+
public double getDoubleValue() throws IOException {
109107
checkNumber();
110108
return Double.parseDouble(currentText);
111109
}
112110

113111
@Override
114-
public long getLongValue() {
112+
public long getLongValue() throws IOException {
115113
checkNumber();
116114
return Long.parseLong(currentText);
117115
}
118116

119-
private void checkNumber() {
120-
Preconditions.checkArgument(
121-
currentToken == JsonToken.VALUE_NUMBER_INT || currentToken == JsonToken.VALUE_NUMBER_FLOAT);
117+
private void checkNumber() throws IOException {
118+
if (currentToken != JsonToken.VALUE_NUMBER_INT
119+
&& currentToken != JsonToken.VALUE_NUMBER_FLOAT) {
120+
throw new IOException("Token is not a number");
121+
}
122122
}
123123

124124
@Override

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

+16-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010 Google Inc.
2+
* Copyright 2010 Google Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
55
* in compliance with the License. You may obtain a copy of the License at
@@ -17,8 +17,7 @@
1717
import com.google.api.client.json.JsonFactory;
1818
import com.google.api.client.json.JsonParser;
1919
import com.google.api.client.test.json.AbstractJsonFactoryTest;
20-
import com.google.common.base.Charsets;
21-
import java.io.ByteArrayInputStream;
20+
import java.io.IOException;
2221
import java.util.ArrayList;
2322

2423
/**
@@ -80,10 +79,19 @@ public final void testToPrettyString_Feed() throws Exception {
8079
assertEquals(JSON_FEED_PRETTY, newFactory().toPrettyString(feed));
8180
}
8281

83-
public final void testParse_directValue() throws Exception {
84-
byte[] jsonData = Charsets.UTF_8.encode("123").array();
85-
JsonParser jp =
86-
newFactory().createJsonParser(new ByteArrayInputStream(jsonData), Charsets.UTF_8);
87-
assertEquals(123, jp.parse(Integer.class, true));
82+
public final void testParse_directValue() throws IOException {
83+
JsonParser parser = newFactory().createJsonParser("123");
84+
assertEquals(123, parser.parse(Integer.class, true));
85+
}
86+
87+
public final void testGetByteValue() throws IOException {
88+
JsonParser parser = newFactory().createJsonParser("123");
89+
90+
try {
91+
parser.getByteValue();
92+
fail("should throw IOException");
93+
} catch (IOException ex) {
94+
assertNotNull(ex.getMessage());
95+
}
8896
}
8997
}

google-http-client-jackson2/pom.xml

-5
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,5 @@
8080
<groupId>com.fasterxml.jackson.core</groupId>
8181
<artifactId>jackson-core</artifactId>
8282
</dependency>
83-
<dependency>
84-
<groupId>com.google.guava</groupId>
85-
<artifactId>guava</artifactId>
86-
<scope>test</scope>
87-
</dependency>
8883
</dependencies>
8984
</project>

google-http-client-jackson2/src/test/java/com/google/api/client/json/jackson2/JacksonFactoryTest.java

+15-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012 Google Inc.
2+
* Copyright 2012 Google Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
55
* in compliance with the License. You may obtain a copy of the License at
@@ -18,8 +18,7 @@
1818
import com.google.api.client.json.JsonParser;
1919
import com.google.api.client.test.json.AbstractJsonFactoryTest;
2020
import com.google.api.client.util.StringUtils;
21-
import com.google.common.base.Charsets;
22-
import java.io.ByteArrayInputStream;
21+
import java.io.IOException;
2322
import java.util.ArrayList;
2423

2524
/**
@@ -74,9 +73,18 @@ public final void testToPrettyString_Feed() throws Exception {
7473
}
7574

7675
public final void testParse_directValue() throws Exception {
77-
byte[] jsonData = Charsets.UTF_8.encode("123").array();
78-
JsonParser jp =
79-
newFactory().createJsonParser(new ByteArrayInputStream(jsonData), Charsets.UTF_8);
80-
assertEquals(123, jp.parse(Integer.class, true));
76+
JsonParser parser = newFactory().createJsonParser("123");
77+
assertEquals(123, parser.parse(Integer.class, true));
78+
}
79+
80+
public final void testGetByteValue() throws IOException {
81+
JsonParser parser = newFactory().createJsonParser("123");
82+
83+
try {
84+
parser.getByteValue();
85+
fail("should throw IOException");
86+
} catch (IOException ex) {
87+
assertNotNull(ex.getMessage());
88+
}
8189
}
8290
}

google-http-client-test/src/main/java/com/google/api/client/test/json/AbstractJsonParserTest.java

+24
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.math.BigDecimal;
2323
import java.nio.charset.StandardCharsets;
2424
import junit.framework.TestCase;
25+
import org.junit.Assert;
2526

2627
public abstract class AbstractJsonParserTest extends TestCase {
2728

@@ -44,6 +45,29 @@ public void testParse_basic() throws IOException {
4445
assertEquals(Boolean.FALSE, json.get("boolValue"));
4546
}
4647

48+
public void testGetWrongType() throws IOException {
49+
JsonObjectParser parser = new JsonObjectParser(newJsonFactory());
50+
InputStream inputStream = new ByteArrayInputStream(TEST_JSON.getBytes(StandardCharsets.UTF_8));
51+
GenericJson json = parser.parseAndClose(inputStream, StandardCharsets.UTF_8, GenericJson.class);
52+
assertTrue(json.get("strValue") instanceof String);
53+
assertEquals("bar", json.get("strValue"));
54+
assertTrue(json.get("intValue") instanceof BigDecimal);
55+
assertEquals(new BigDecimal(123), json.get("intValue"));
56+
assertTrue(json.get("boolValue") instanceof Boolean);
57+
assertEquals(Boolean.FALSE, json.get("boolValue"));
58+
}
59+
60+
public void testParse_badJson() throws IOException {
61+
JsonObjectParser parser = new JsonObjectParser(newJsonFactory());
62+
InputStream inputStream = new ByteArrayInputStream("not json".getBytes(StandardCharsets.UTF_8));
63+
try {
64+
parser.parseAndClose(inputStream, StandardCharsets.UTF_8, GenericJson.class);
65+
fail("Malformed JSON not detected");
66+
} catch (IOException ex) {
67+
Assert.assertNotNull(ex.getMessage());
68+
}
69+
}
70+
4771
public void testParse_bigDecimal() throws IOException {
4872
JsonObjectParser parser = new JsonObjectParser(newJsonFactory());
4973
InputStream inputStream =

0 commit comments

Comments
 (0)