Adding JsonReader.setLenient() to handle malformed JSON strings.
Also replacing setIndentSpaces() with a more general purpose method, setIndent(). Change-Id: I64fbe4901aec23de5392362c1d40b77bc2b5566b
This commit is contained in:
@@ -180354,6 +180354,19 @@
|
||||
<exception name="IOException" type="java.io.IOException">
|
||||
</exception>
|
||||
</method>
|
||||
<method name="setLenient"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="lenient" type="boolean">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="skipValue"
|
||||
return="void"
|
||||
abstract="false"
|
||||
@@ -180424,6 +180437,8 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<implements name="java.io.Closeable">
|
||||
</implements>
|
||||
<constructor name="JsonWriter"
|
||||
type="android.util.JsonWriter"
|
||||
static="false"
|
||||
@@ -180540,7 +180555,7 @@
|
||||
<exception name="IOException" type="java.io.IOException">
|
||||
</exception>
|
||||
</method>
|
||||
<method name="setIndentSpaces"
|
||||
<method name="setIndent"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
@@ -180550,7 +180565,7 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="indent" type="int">
|
||||
<parameter name="indent" type="java.lang.String">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="value"
|
||||
@@ -272628,7 +272643,7 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="loop" type="boolean">
|
||||
<parameter name="disable" type="boolean">
|
||||
</parameter>
|
||||
<exception name="SocketException" type="java.net.SocketException">
|
||||
</exception>
|
||||
@@ -274187,7 +274202,7 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="value" type="boolean">
|
||||
<parameter name="keepAlive" type="boolean">
|
||||
</parameter>
|
||||
<exception name="SocketException" type="java.net.SocketException">
|
||||
</exception>
|
||||
|
||||
@@ -172,6 +172,9 @@ public final class JsonReader implements Closeable {
|
||||
/** The input JSON. */
|
||||
private final Reader in;
|
||||
|
||||
/** True to accept non-spec compliant JSON */
|
||||
private boolean lenient = false;
|
||||
|
||||
/**
|
||||
* Use a manual buffer to easily read and unread upcoming characters, and
|
||||
* also so we can create strings without an intermediate StringBuilder.
|
||||
@@ -207,9 +210,6 @@ public final class JsonReader implements Closeable {
|
||||
/** The text of the next literal value. */
|
||||
private String value;
|
||||
|
||||
// TODO: make this parser strict and offer an optional lenient mode?
|
||||
// TODO: document how this reader is non-strict
|
||||
|
||||
/**
|
||||
* Creates a new instance that reads a JSON-encoded stream from {@code in}.
|
||||
*/
|
||||
@@ -220,6 +220,31 @@ public final class JsonReader implements Closeable {
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure this parser to be be liberal in what it accepts. By default,
|
||||
* this parser is strict and only accepts JSON as specified by <a
|
||||
* href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>. Setting the
|
||||
* parser to lenient causes it to ignore the following syntax errors:
|
||||
*
|
||||
* <ul>
|
||||
* <li>End of line comments starting with {@code //} or {@code #} and
|
||||
* ending with a newline character.
|
||||
* <li>C-style comments starting with {@code /*} and ending with
|
||||
* {@code *}{@code /}. Such comments may not be nested.
|
||||
* <li>Names that are unquoted or {@code 'single quoted'}.
|
||||
* <li>Strings that are unquoted or {@code 'single quoted'}.
|
||||
* <li>Array elements separated by {@code ;} instead of {@code ,}.
|
||||
* <li>Unnecessary array separators. These are interpreted as if null
|
||||
* was the omitted value.
|
||||
* <li>Names and values separated by {@code =} or {@code =>} instead of
|
||||
* {@code :}.
|
||||
* <li>Name/value pairs separated by {@code ;} instead of {@code ,}.
|
||||
* </ul>
|
||||
*/
|
||||
public void setLenient(boolean lenient) {
|
||||
this.lenient = lenient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumes the next token from the JSON stream and asserts that it is the
|
||||
* beginning of a new array.
|
||||
@@ -253,11 +278,12 @@ public final class JsonReader implements Closeable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumes {@code token}.
|
||||
* Consumes {@code expected}.
|
||||
*/
|
||||
private void expect(JsonToken token) throws IOException {
|
||||
if (quickPeek() != token) {
|
||||
throw new IllegalStateException("Expected " + token + " but was " + peek());
|
||||
private void expect(JsonToken expected) throws IOException {
|
||||
quickPeek();
|
||||
if (token != expected) {
|
||||
throw new IllegalStateException("Expected " + expected + " but was " + peek());
|
||||
}
|
||||
advance();
|
||||
}
|
||||
@@ -266,8 +292,8 @@ public final class JsonReader implements Closeable {
|
||||
* Returns true if the current array or object has another element.
|
||||
*/
|
||||
public boolean hasNext() throws IOException {
|
||||
JsonToken peek = quickPeek();
|
||||
return peek != JsonToken.END_OBJECT && peek != JsonToken.END_ARRAY;
|
||||
quickPeek();
|
||||
return token != JsonToken.END_OBJECT && token != JsonToken.END_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -285,11 +311,8 @@ public final class JsonReader implements Closeable {
|
||||
|
||||
/**
|
||||
* Ensures that a token is ready. After this call either {@code token} or
|
||||
* {@code value} will be non-null.
|
||||
*
|
||||
* @return the type of the next token, of {@code null} if it is unknown. For
|
||||
* a definitive result, use {@link #peek()} which decodes the token
|
||||
* type.
|
||||
* {@code value} will be non-null. To ensure {@code token} has a definitive
|
||||
* value, use {@link #peek()}
|
||||
*/
|
||||
private JsonToken quickPeek() throws IOException {
|
||||
if (hasToken) {
|
||||
@@ -347,7 +370,8 @@ public final class JsonReader implements Closeable {
|
||||
* name.
|
||||
*/
|
||||
public String nextName() throws IOException {
|
||||
if (quickPeek() != JsonToken.NAME) {
|
||||
quickPeek();
|
||||
if (token != JsonToken.NAME) {
|
||||
throw new IllegalStateException("Expected a name but was " + peek());
|
||||
}
|
||||
String result = name;
|
||||
@@ -364,8 +388,8 @@ public final class JsonReader implements Closeable {
|
||||
* this reader is closed.
|
||||
*/
|
||||
public String nextString() throws IOException {
|
||||
JsonToken peek = peek();
|
||||
if (value == null || (peek != JsonToken.STRING && peek != JsonToken.NUMBER)) {
|
||||
peek();
|
||||
if (value == null || (token != JsonToken.STRING && token != JsonToken.NUMBER)) {
|
||||
throw new IllegalStateException("Expected a string but was " + peek());
|
||||
}
|
||||
|
||||
@@ -382,8 +406,8 @@ public final class JsonReader implements Closeable {
|
||||
* this reader is closed.
|
||||
*/
|
||||
public boolean nextBoolean() throws IOException {
|
||||
JsonToken peek = quickPeek();
|
||||
if (value == null || peek == JsonToken.STRING) {
|
||||
quickPeek();
|
||||
if (value == null || token == JsonToken.STRING) {
|
||||
throw new IllegalStateException("Expected a boolean but was " + peek());
|
||||
}
|
||||
|
||||
@@ -408,8 +432,8 @@ public final class JsonReader implements Closeable {
|
||||
* reader is closed.
|
||||
*/
|
||||
public void nextNull() throws IOException {
|
||||
JsonToken peek = quickPeek();
|
||||
if (value == null || peek == JsonToken.STRING) {
|
||||
quickPeek();
|
||||
if (value == null || token == JsonToken.STRING) {
|
||||
throw new IllegalStateException("Expected null but was " + peek());
|
||||
}
|
||||
|
||||
@@ -570,36 +594,43 @@ public final class JsonReader implements Closeable {
|
||||
|
||||
private JsonToken nextInArray(boolean firstElement) throws IOException {
|
||||
if (firstElement) {
|
||||
switch (nextNonWhitespace()) {
|
||||
case ']':
|
||||
pop();
|
||||
hasToken = true;
|
||||
return token = JsonToken.END_ARRAY;
|
||||
case ',':
|
||||
case ';':
|
||||
/* a separator without a value first means "null". */
|
||||
// TODO: forbid this in strict mode
|
||||
hasToken = true;
|
||||
return token = JsonToken.NULL;
|
||||
default:
|
||||
replaceTop(JsonScope.NONEMPTY_ARRAY);
|
||||
pos--;
|
||||
}
|
||||
replaceTop(JsonScope.NONEMPTY_ARRAY);
|
||||
} else {
|
||||
/* Look for a comma before each element after the first element. */
|
||||
switch (nextNonWhitespace()) {
|
||||
case ']':
|
||||
pop();
|
||||
hasToken = true;
|
||||
return token = JsonToken.END_ARRAY;
|
||||
case ',':
|
||||
case ';':
|
||||
checkLenient(); // fall-through
|
||||
case ',':
|
||||
break;
|
||||
default:
|
||||
throw syntaxError("Unterminated array");
|
||||
}
|
||||
}
|
||||
|
||||
return nextValue();
|
||||
switch (nextNonWhitespace()) {
|
||||
case ']':
|
||||
if (firstElement) {
|
||||
pop();
|
||||
hasToken = true;
|
||||
return token = JsonToken.END_ARRAY;
|
||||
}
|
||||
// fall-through to handle ",]"
|
||||
case ';':
|
||||
case ',':
|
||||
/* In lenient mode, a 0-length literal means 'null' */
|
||||
checkLenient();
|
||||
pos--;
|
||||
hasToken = true;
|
||||
value = "null";
|
||||
return token = JsonToken.NULL;
|
||||
default:
|
||||
pos--;
|
||||
return nextValue();
|
||||
}
|
||||
}
|
||||
|
||||
private JsonToken nextInObject(boolean firstElement) throws IOException {
|
||||
@@ -636,10 +667,12 @@ public final class JsonReader implements Closeable {
|
||||
int quote = nextNonWhitespace();
|
||||
switch (quote) {
|
||||
case '\'':
|
||||
checkLenient(); // fall-through
|
||||
case '"':
|
||||
name = nextString((char) quote);
|
||||
break;
|
||||
default:
|
||||
checkLenient();
|
||||
pos--;
|
||||
name = nextLiteral();
|
||||
if (name.isEmpty()) {
|
||||
@@ -653,19 +686,21 @@ public final class JsonReader implements Closeable {
|
||||
}
|
||||
|
||||
private JsonToken objectValue() throws IOException {
|
||||
// TODO: accept only ":" in strict mode
|
||||
|
||||
/*
|
||||
* Read the name/value separator. Usually a colon ':', an equals sign
|
||||
* '=', or an arrow "=>". The last two are bogus but we include them
|
||||
* because that's what org.json does.
|
||||
* Read the name/value separator. Usually a colon ':'. In lenient mode
|
||||
* we also accept an equals sign '=', or an arrow "=>".
|
||||
*/
|
||||
int separator = nextNonWhitespace();
|
||||
if (separator != ':' && separator != '=') {
|
||||
throw syntaxError("Expected ':'");
|
||||
}
|
||||
if (separator == '=' && (pos < limit || fillBuffer(1)) && buffer[pos] == '>') {
|
||||
pos++;
|
||||
switch (nextNonWhitespace()) {
|
||||
case ':':
|
||||
break;
|
||||
case '=':
|
||||
checkLenient();
|
||||
if ((pos < limit || fillBuffer(1)) && buffer[pos] == '>') {
|
||||
pos++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw syntaxError("Expected ':'");
|
||||
}
|
||||
|
||||
replaceTop(JsonScope.NONEMPTY_OBJECT);
|
||||
@@ -686,6 +721,7 @@ public final class JsonReader implements Closeable {
|
||||
return token = JsonToken.BEGIN_ARRAY;
|
||||
|
||||
case '\'':
|
||||
checkLenient(); // fall-through
|
||||
case '"':
|
||||
value = nextString((char) c);
|
||||
hasToken = true;
|
||||
@@ -722,8 +758,6 @@ public final class JsonReader implements Closeable {
|
||||
}
|
||||
|
||||
private int nextNonWhitespace() throws IOException {
|
||||
// TODO: no comments in strict mode
|
||||
|
||||
while (pos < limit || fillBuffer(1)) {
|
||||
int c = buffer[pos++];
|
||||
switch (c) {
|
||||
@@ -738,6 +772,7 @@ public final class JsonReader implements Closeable {
|
||||
return c;
|
||||
}
|
||||
|
||||
checkLenient();
|
||||
char peek = buffer[pos];
|
||||
switch (peek) {
|
||||
case '*':
|
||||
@@ -765,6 +800,7 @@ public final class JsonReader implements Closeable {
|
||||
* specify this behaviour, but it's required to parse
|
||||
* existing documents. See http://b/2571423.
|
||||
*/
|
||||
checkLenient();
|
||||
skipToEndOfLine();
|
||||
continue;
|
||||
|
||||
@@ -776,6 +812,12 @@ public final class JsonReader implements Closeable {
|
||||
throw syntaxError("End of input");
|
||||
}
|
||||
|
||||
private void checkLenient() throws IOException {
|
||||
if (!lenient) {
|
||||
throw syntaxError("Use JsonReader.setLenient(true) to accept malformed JSON");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances the position until after the next newline character. If the line
|
||||
* is terminated by "\r\n", the '\n' must be consumed as whitespace by the
|
||||
@@ -853,9 +895,6 @@ public final class JsonReader implements Closeable {
|
||||
* does not consume the delimiter character.
|
||||
*/
|
||||
private String nextLiteral() throws IOException {
|
||||
// TODO: use a much smaller set of permitted literal characters in strict mode;
|
||||
// these characters are derived from org.json's lenient mode
|
||||
|
||||
StringBuilder builder = null;
|
||||
do {
|
||||
/* the index of the first character not yet appended to the builder. */
|
||||
@@ -863,17 +902,19 @@ public final class JsonReader implements Closeable {
|
||||
while (pos < limit) {
|
||||
int c = buffer[pos++];
|
||||
switch (c) {
|
||||
case '/':
|
||||
case '\\':
|
||||
case ';':
|
||||
case '#':
|
||||
case '=':
|
||||
checkLenient(); // fall-through
|
||||
|
||||
case '{':
|
||||
case '}':
|
||||
case '[':
|
||||
case ']':
|
||||
case '/':
|
||||
case '\\':
|
||||
case ':':
|
||||
case '=':
|
||||
case ',':
|
||||
case ';':
|
||||
case '#':
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\f':
|
||||
@@ -965,7 +1006,7 @@ public final class JsonReader implements Closeable {
|
||||
/**
|
||||
* Assigns {@code nextToken} based on the value of {@code nextValue}.
|
||||
*/
|
||||
private void decodeLiteral() {
|
||||
private void decodeLiteral() throws IOException {
|
||||
if (value.equalsIgnoreCase("null")) {
|
||||
token = JsonToken.NULL;
|
||||
} else if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) {
|
||||
@@ -975,7 +1016,8 @@ public final class JsonReader implements Closeable {
|
||||
Double.parseDouble(value); // this work could potentially be cached
|
||||
token = JsonToken.NUMBER;
|
||||
} catch (NumberFormatException ignored) {
|
||||
/* an unquoted string. This document is not well-formed! */
|
||||
// this must be an unquoted string
|
||||
checkLenient();
|
||||
token = JsonToken.STRING;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
package android.util;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -117,7 +117,7 @@ import java.util.List;
|
||||
* Instances of this class are not thread safe. Calls that would result in a
|
||||
* malformed JSON string will fail with an {@link IllegalStateException}.
|
||||
*/
|
||||
public final class JsonWriter {
|
||||
public final class JsonWriter implements Closeable {
|
||||
|
||||
/** The output data, containing at most one top-level array or object. */
|
||||
private final Writer out;
|
||||
@@ -151,23 +151,20 @@ public final class JsonWriter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of spaces to indent each line in the encoded document.
|
||||
* If {@code indent == 0} the encoded document will be compact. If {@code
|
||||
* indent > 0}, the encoded document will be more human-readable.
|
||||
* Sets the indentation string to be repeated for each level of indentation
|
||||
* in the encoded document. If {@code indent.isEmpty()} the encoded document
|
||||
* will be compact. Otherwise the encoded document will be more
|
||||
* human-readable.
|
||||
*
|
||||
* @param indent a string containing only whitespace.
|
||||
*/
|
||||
public void setIndentSpaces(int indent) {
|
||||
if (indent < 0) {
|
||||
throw new IllegalArgumentException("indent < 0");
|
||||
}
|
||||
|
||||
if (indent > 0) {
|
||||
char[] indentChars = new char[indent];
|
||||
Arrays.fill(indentChars, ' ');
|
||||
this.indent = new String(indentChars);
|
||||
this.separator = ": ";
|
||||
} else {
|
||||
public void setIndent(String indent) {
|
||||
if (indent.isEmpty()) {
|
||||
this.indent = null;
|
||||
this.separator = ":";
|
||||
} else {
|
||||
this.indent = indent;
|
||||
this.separator = ": ";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,14 @@ public final class JsonReaderTest extends TestCase {
|
||||
assertEquals(JsonToken.END_DOCUMENT, reader.peek());
|
||||
}
|
||||
|
||||
public void testReadEmptyArray() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("[]"));
|
||||
reader.beginArray();
|
||||
assertFalse(reader.hasNext());
|
||||
reader.endArray();
|
||||
assertEquals(JsonToken.END_DOCUMENT, reader.peek());
|
||||
}
|
||||
|
||||
public void testReadObject() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader(
|
||||
"{\"a\": \"android\", \"b\": \"banana\"}"));
|
||||
@@ -44,6 +52,14 @@ public final class JsonReaderTest extends TestCase {
|
||||
assertEquals(JsonToken.END_DOCUMENT, reader.peek());
|
||||
}
|
||||
|
||||
public void testReadEmptyObject() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("{}"));
|
||||
reader.beginObject();
|
||||
assertFalse(reader.hasNext());
|
||||
reader.endObject();
|
||||
assertEquals(JsonToken.END_DOCUMENT, reader.peek());
|
||||
}
|
||||
|
||||
public void testSkipObject() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader(
|
||||
"{\"a\": { \"c\": [], \"d\": [true, true, {}] }, \"b\": \"banana\"}"));
|
||||
@@ -412,4 +428,256 @@ public final class JsonReaderTest extends TestCase {
|
||||
} catch (IllegalStateException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testStrictNameValueSeparator() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("{\"a\"=true}"));
|
||||
reader.beginObject();
|
||||
assertEquals("a", reader.nextName());
|
||||
try {
|
||||
reader.nextBoolean();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
|
||||
reader = new JsonReader(new StringReader("{\"a\"=>true}"));
|
||||
reader.beginObject();
|
||||
assertEquals("a", reader.nextName());
|
||||
try {
|
||||
reader.nextBoolean();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testLenientNameValueSeparator() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("{\"a\"=true}"));
|
||||
reader.setLenient(true);
|
||||
reader.beginObject();
|
||||
assertEquals("a", reader.nextName());
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
|
||||
reader = new JsonReader(new StringReader("{\"a\"=>true}"));
|
||||
reader.setLenient(true);
|
||||
reader.beginObject();
|
||||
assertEquals("a", reader.nextName());
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
}
|
||||
|
||||
public void testStrictComments() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("[// comment \n true]"));
|
||||
reader.beginArray();
|
||||
try {
|
||||
reader.nextBoolean();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
|
||||
reader = new JsonReader(new StringReader("[# comment \n true]"));
|
||||
reader.beginArray();
|
||||
try {
|
||||
reader.nextBoolean();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
|
||||
reader = new JsonReader(new StringReader("[/* comment */ true]"));
|
||||
reader.beginArray();
|
||||
try {
|
||||
reader.nextBoolean();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testLenientComments() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("[// comment \n true]"));
|
||||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
|
||||
reader = new JsonReader(new StringReader("[# comment \n true]"));
|
||||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
|
||||
reader = new JsonReader(new StringReader("[/* comment */ true]"));
|
||||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
}
|
||||
|
||||
public void testStrictUnquotedNames() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("{a:true}"));
|
||||
reader.beginObject();
|
||||
try {
|
||||
reader.nextName();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testLenientUnquotedNames() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("{a:true}"));
|
||||
reader.setLenient(true);
|
||||
reader.beginObject();
|
||||
assertEquals("a", reader.nextName());
|
||||
}
|
||||
|
||||
public void testStrictSingleQuotedNames() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("{'a':true}"));
|
||||
reader.beginObject();
|
||||
try {
|
||||
reader.nextName();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testLenientSingleQuotedNames() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("{'a':true}"));
|
||||
reader.setLenient(true);
|
||||
reader.beginObject();
|
||||
assertEquals("a", reader.nextName());
|
||||
}
|
||||
|
||||
public void testStrictUnquotedStrings() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("[a]"));
|
||||
reader.beginArray();
|
||||
try {
|
||||
reader.nextString();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testLenientUnquotedStrings() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("[a]"));
|
||||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
assertEquals("a", reader.nextString());
|
||||
}
|
||||
|
||||
public void testStrictSingleQuotedStrings() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("['a']"));
|
||||
reader.beginArray();
|
||||
try {
|
||||
reader.nextString();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testLenientSingleQuotedStrings() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("['a']"));
|
||||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
assertEquals("a", reader.nextString());
|
||||
}
|
||||
|
||||
public void testStrictSemicolonDelimitedArray() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("[true;true]"));
|
||||
reader.beginArray();
|
||||
try {
|
||||
reader.nextBoolean();
|
||||
reader.nextBoolean();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testLenientSemicolonDelimitedArray() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("[true;true]"));
|
||||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
}
|
||||
|
||||
public void testStrictSemicolonDelimitedNameValuePair() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("{\"a\":true;\"b\":true}"));
|
||||
reader.beginObject();
|
||||
assertEquals("a", reader.nextName());
|
||||
try {
|
||||
reader.nextBoolean();
|
||||
reader.nextName();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testLenientSemicolonDelimitedNameValuePair() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("{\"a\":true;\"b\":true}"));
|
||||
reader.setLenient(true);
|
||||
reader.beginObject();
|
||||
assertEquals("a", reader.nextName());
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
assertEquals("b", reader.nextName());
|
||||
}
|
||||
|
||||
public void testStrictUnnecessaryArraySeparators() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("[true,,true]"));
|
||||
reader.beginArray();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
try {
|
||||
reader.nextNull();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
|
||||
reader = new JsonReader(new StringReader("[,true]"));
|
||||
reader.beginArray();
|
||||
try {
|
||||
reader.nextNull();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
|
||||
reader = new JsonReader(new StringReader("[true,]"));
|
||||
reader.beginArray();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
try {
|
||||
reader.nextNull();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
|
||||
reader = new JsonReader(new StringReader("[,]"));
|
||||
reader.beginArray();
|
||||
try {
|
||||
reader.nextNull();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testLenientUnnecessaryArraySeparators() throws IOException {
|
||||
JsonReader reader = new JsonReader(new StringReader("[true,,true]"));
|
||||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
reader.nextNull();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
reader.endArray();
|
||||
|
||||
reader = new JsonReader(new StringReader("[,true]"));
|
||||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
reader.nextNull();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
reader.endArray();
|
||||
|
||||
reader = new JsonReader(new StringReader("[true,]"));
|
||||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
reader.nextNull();
|
||||
reader.endArray();
|
||||
|
||||
reader = new JsonReader(new StringReader("[,]"));
|
||||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
reader.nextNull();
|
||||
reader.nextNull();
|
||||
reader.endArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ public final class JsonWriterTest extends TestCase {
|
||||
public void testPrettyPrintObject() throws IOException {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
JsonWriter jsonWriter = new JsonWriter(stringWriter);
|
||||
jsonWriter.setIndentSpaces(3);
|
||||
jsonWriter.setIndent(" ");
|
||||
|
||||
jsonWriter.beginObject();
|
||||
jsonWriter.name("a").value(true);
|
||||
@@ -383,7 +383,7 @@ public final class JsonWriterTest extends TestCase {
|
||||
public void testPrettyPrintArray() throws IOException {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
JsonWriter jsonWriter = new JsonWriter(stringWriter);
|
||||
jsonWriter.setIndentSpaces(3);
|
||||
jsonWriter.setIndent(" ");
|
||||
|
||||
jsonWriter.beginArray();
|
||||
jsonWriter.value(true);
|
||||
|
||||
Reference in New Issue
Block a user