Required strings to be quoted even in lenient mode.

As far as Inderjeet and I can tell, this is consistent with Gson 1.5.
This commit is contained in:
Joel Leitch 2010-11-16 22:14:40 +00:00
parent 279649986e
commit 0a3f5fa801
6 changed files with 42 additions and 46 deletions

View File

@ -17,9 +17,7 @@
package com.google.gson; package com.google.gson;
import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter; import com.google.gson.stream.JsonWriter;
import com.google.gson.stream.MalformedJsonException;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
@ -457,7 +455,6 @@ public final class Gson {
public <T> T fromJson(Reader json, Class<T> classOfT) throws JsonSyntaxException, JsonIOException { public <T> T fromJson(Reader json, Class<T> classOfT) throws JsonSyntaxException, JsonIOException {
JsonReader jsonReader = new JsonReader(json); JsonReader jsonReader = new JsonReader(json);
Object object = fromJson(jsonReader, classOfT); Object object = fromJson(jsonReader, classOfT);
assertFullConsumption(object, jsonReader);
return Primitives.wrap(classOfT).cast(object); return Primitives.wrap(classOfT).cast(object);
} }
@ -482,21 +479,7 @@ public final class Gson {
*/ */
public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException { public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
JsonReader jsonReader = new JsonReader(json); JsonReader jsonReader = new JsonReader(json);
T object = this.<T>fromJson(jsonReader, typeOfT); return this.<T>fromJson(jsonReader, typeOfT);
assertFullConsumption(object, jsonReader);
return object;
}
private static void assertFullConsumption(Object obj, JsonReader reader) {
try {
if (obj != null && reader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
} catch (MalformedJsonException e) {
throw new JsonSyntaxException(e);
} catch (IOException e) {
throw new JsonIOException(e);
}
} }
/** /**

View File

@ -16,11 +16,8 @@
package com.google.gson; package com.google.gson;
import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.MalformedJsonException;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.io.StringReader; import java.io.StringReader;
@ -54,20 +51,8 @@ public final class JsonParser {
* @since 1.3 * @since 1.3
*/ */
public JsonElement parse(Reader json) throws JsonIOException, JsonSyntaxException { public JsonElement parse(Reader json) throws JsonIOException, JsonSyntaxException {
try { JsonReader jsonReader = new JsonReader(json);
JsonReader jsonReader = new JsonReader(json); return parse(jsonReader);
JsonElement element = parse(jsonReader);
if (!element.isJsonNull() && jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonSyntaxException("Did not consume the entire document.");
}
return element;
} catch (MalformedJsonException e) {
throw new JsonSyntaxException(e);
} catch (IOException e) {
throw new JsonIOException(e);
} catch (NumberFormatException e) {
throw new JsonSyntaxException(e);
}
} }
/** /**
@ -75,6 +60,7 @@ public final class JsonParser {
* *
* @throws JsonParseException if there is an IOException or if the specified * @throws JsonParseException if there is an IOException or if the specified
* text is not valid JSON * text is not valid JSON
* @since 1.6
*/ */
public JsonElement parse(JsonReader json) throws JsonIOException, JsonSyntaxException { public JsonElement parse(JsonReader json) throws JsonIOException, JsonSyntaxException {
boolean lenient = json.isLenient(); boolean lenient = json.isLenient();

View File

@ -402,17 +402,17 @@ public final class JsonReader implements Closeable {
// fast forward through the leading whitespace // fast forward through the leading whitespace
nextNonWhitespace(); nextNonWhitespace();
pos--; pos--;
if (pos + NON_EXECUTE_PREFIX.length > limit && !fillBuffer(NON_EXECUTE_PREFIX.length)) { if (pos + NON_EXECUTE_PREFIX.length > limit && !fillBuffer(NON_EXECUTE_PREFIX.length)) {
return; return;
} }
for (int i = 0; i < NON_EXECUTE_PREFIX.length; i++) { for (int i = 0; i < NON_EXECUTE_PREFIX.length; i++) {
if (buffer[pos + i] != NON_EXECUTE_PREFIX[i]) { if (buffer[pos + i] != NON_EXECUTE_PREFIX[i]) {
return; // not a security token! return; // not a security token!
} }
} }
// we consumed a security token! // we consumed a security token!
pos += NON_EXECUTE_PREFIX.length; pos += NON_EXECUTE_PREFIX.length;
} }
@ -1097,8 +1097,7 @@ public final class JsonReader implements Closeable {
token = JsonToken.NUMBER; token = JsonToken.NUMBER;
} catch (NumberFormatException ignored) { } catch (NumberFormatException ignored) {
// this must be an unquoted string // this must be an unquoted string
checkLenient(); throw syntaxError("invalid number or unquoted string");
token = JsonToken.STRING;
} }
} }
} }

View File

@ -39,6 +39,20 @@ public class JsonParserTest extends TestCase {
parser = new JsonParser(); parser = new JsonParser();
} }
public void testParseSingleWordFails() {
try {
parser.parse("Word");
fail();
} catch (JsonSyntaxException expected) {}
}
public void testParseUnquotedStringArrayFails() {
try {
parser.parse("[a,b,c]");
fail();
} catch (JsonSyntaxException expected) {}
}
public void testParseString() { public void testParseString() {
String json = "{a:10,b:'c'}"; String json = "{a:10,b:'c'}";
JsonElement e = parser.parse(json); JsonElement e = parser.parse(json);
@ -58,7 +72,14 @@ public class JsonParserTest extends TestCase {
assertTrue(e.isJsonNull()); assertTrue(e.isJsonNull());
} }
public void testParseUnquotedStringSentence() { public void testParseUnquotedSingleWordStringFails() {
try {
parser.parse("Test");
fail();
} catch (JsonSyntaxException expected) { }
}
public void testParseUnquotedMultiWordStringFails() {
String unquotedSentence = "Test is a test..blah blah"; String unquotedSentence = "Test is a test..blah blah";
try { try {
parser.parse(unquotedSentence); parser.parse(unquotedSentence);

View File

@ -571,7 +571,12 @@ public class PrimitiveTest extends TestCase {
assertEquals(value, actual); assertEquals(value, actual);
} }
public void testUnquotedStringDeserialization() throws Exception { public void testUnquotedStringDeserializationFails() throws Exception {
try {
gson.fromJson("UnquotedSingleWord", String.class);
fail();
} catch (JsonSyntaxException expected) { }
String value = "String Blah Blah Blah...1, 2, 3"; String value = "String Blah Blah Blah...1, 2, 3";
try { try {
gson.fromJson(value, String.class); gson.fromJson(value, String.class);

View File

@ -557,7 +557,7 @@ public final class JsonReaderTest extends TestCase {
try { try {
reader.nextString(); reader.nextString();
fail(); fail();
} catch (IOException expected) { } catch (MalformedJsonException expected) {
} }
} }
@ -565,7 +565,10 @@ public final class JsonReaderTest extends TestCase {
JsonReader reader = new JsonReader(new StringReader("[a]")); JsonReader reader = new JsonReader(new StringReader("[a]"));
reader.setLenient(true); reader.setLenient(true);
reader.beginArray(); reader.beginArray();
assertEquals("a", reader.nextString()); try {
reader.nextString();
fail();
} catch (MalformedJsonException expected) { }
} }
public void testStrictSingleQuotedStrings() throws IOException { public void testStrictSingleQuotedStrings() throws IOException {
@ -757,9 +760,8 @@ public final class JsonReaderTest extends TestCase {
public void testLenientPartialNonExecutePrefix() throws IOException { public void testLenientPartialNonExecutePrefix() throws IOException {
JsonReader reader = new JsonReader(new StringReader(")]}' []")); JsonReader reader = new JsonReader(new StringReader(")]}' []"));
reader.setLenient(true); reader.setLenient(true);
assertEquals(")", reader.nextString()); // lenient is almost too lenient!
try { try {
reader.peek(); reader.beginArray();
fail(); fail();
} catch (IOException expected) { } catch (IOException expected) {
} }