Loading api/current.xml +70 −16 Original line number Diff line number Diff line Loading @@ -198616,6 +198616,17 @@ <exception name="IOException" type="java.io.IOException"> </exception> </method> <method name="isLenient" return="boolean" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="nextBoolean" return="boolean" abstract="false" Loading Loading @@ -198746,21 +198757,6 @@ <exception name="IOException" type="java.io.IOException"> </exception> </method> <method name="syntaxError" return="java.io.IOException" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="message" type="java.lang.String"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> </method> </class> <class name="JsonToken" extends="java.lang.Enum" Loading Loading @@ -198893,6 +198889,17 @@ <exception name="IOException" type="java.io.IOException"> </exception> </method> <method name="isLenient" return="boolean" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="name" return="android.util.JsonWriter" abstract="false" Loading Loading @@ -198934,6 +198941,19 @@ <parameter name="indent" type="java.lang.String"> </parameter> </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="value" return="android.util.JsonWriter" abstract="false" Loading Loading @@ -198994,6 +199014,21 @@ <exception name="IOException" type="java.io.IOException"> </exception> </method> <method name="value" return="android.util.JsonWriter" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="value" type="java.lang.Number"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> </method> </class> <class name="Log" extends="java.lang.Object" Loading Loading @@ -199373,6 +199408,25 @@ </parameter> </method> </class> <class name="MalformedJsonException" extends="java.io.IOException" abstract="false" static="false" final="true" deprecated="not deprecated" visibility="public" > <constructor name="MalformedJsonException" type="android.util.MalformedJsonException" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="message" type="java.lang.String"> </parameter> </constructor> </class> <class name="MonthDisplayHelper" extends="java.lang.Object" abstract="false" Loading Loading @@ -258003,7 +258057,7 @@ deprecated="not deprecated" visibility="public" > <parameter name="t" type="T"> <parameter name="arg0" type="T"> </parameter> </method> </interface> core/java/android/util/JsonReader.java +21 −13 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.util; import java.io.EOFException; import java.io.IOException; import java.io.Reader; import java.io.Closeable; Loading Loading @@ -248,6 +249,13 @@ public final class JsonReader implements Closeable { this.lenient = lenient; } /** * Returns true if this parser is liberal in what it accepts. */ public boolean isLenient() { return lenient; } /** * Consumes the next token from the JSON stream and asserts that it is the * beginning of a new array. Loading Loading @@ -311,7 +319,7 @@ public final class JsonReader implements Closeable { case EMPTY_DOCUMENT: replaceTop(JsonScope.NONEMPTY_DOCUMENT); JsonToken firstToken = nextValue(); if (token != JsonToken.BEGIN_ARRAY && token != JsonToken.BEGIN_OBJECT) { if (!lenient && token != JsonToken.BEGIN_ARRAY && token != JsonToken.BEGIN_OBJECT) { throw new IOException( "Expected JSON document to start with '[' or '{' but was " + token); } Loading @@ -327,7 +335,15 @@ public final class JsonReader implements Closeable { case NONEMPTY_OBJECT: return nextInObject(false); case NONEMPTY_DOCUMENT: return token = JsonToken.END_DOCUMENT; try { JsonToken token = nextValue(); if (lenient) { return token; } throw syntaxError("Expected EOF"); } catch (EOFException e) { return token = JsonToken.END_DOCUMENT; // TODO: avoid throwing here? } case CLOSED: throw new IllegalStateException("JsonReader is closed"); default: Loading Loading @@ -758,7 +774,7 @@ public final class JsonReader implements Closeable { } } throw syntaxError("End of input"); throw new EOFException("End of input"); } private void checkLenient() throws IOException { Loading Loading @@ -1030,8 +1046,6 @@ public final class JsonReader implements Closeable { * form -12.34e+56. Fractional and exponential parts are optional. Leading * zeroes are not allowed in the value or exponential part, but are allowed * in the fraction. * * <p>This has a side effect of setting isInteger. */ private JsonToken decodeNumber(char[] chars, int offset, int length) { int i = offset; Loading Loading @@ -1085,8 +1099,8 @@ public final class JsonReader implements Closeable { * Throws a new IO exception with the given message and a context snippet * with this reader's content. */ public IOException syntaxError(String message) throws IOException { throw new JsonSyntaxException(message + " near " + getSnippet()); private IOException syntaxError(String message) throws IOException { throw new MalformedJsonException(message + " near " + getSnippet()); } private CharSequence getSnippet() { Loading @@ -1097,10 +1111,4 @@ public final class JsonReader implements Closeable { snippet.append(buffer, pos, afterPos); return snippet; } private static class JsonSyntaxException extends IOException { private JsonSyntaxException(String s) { super(s); } } } core/java/android/util/JsonWriter.java +50 −4 Original line number Diff line number Diff line Loading @@ -138,6 +138,8 @@ public final class JsonWriter implements Closeable { */ private String separator = ":"; private boolean lenient; /** * Creates a new instance that writes a JSON-encoded stream to {@code out}. * For best performance, ensure {@link Writer} is buffered; wrapping in Loading Loading @@ -168,6 +170,29 @@ public final class JsonWriter implements Closeable { } } /** * Configure this writer to relax its syntax rules. By default, this writer * only emits well-formed JSON as specified by <a * href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>. Setting the writer * to lenient permits the following: * <ul> * <li>Top-level values of any type. With strict writing, the top-level * value must be an object or an array. * <li>Numbers may be {@link Double#isNaN() NaNs} or {@link * Double#isInfinite() infinities}. * </ul> */ public void setLenient(boolean lenient) { this.lenient = lenient; } /** * Returns true if this writer has relaxed syntax rules. */ public boolean isLenient() { return lenient; } /** * Begins encoding a new array. Each call to this method must be paired with * a call to {@link #endArray}. Loading Loading @@ -306,11 +331,11 @@ public final class JsonWriter implements Closeable { * Encodes {@code value}. * * @param value a finite value. May not be {@link Double#isNaN() NaNs} or * {@link Double#isInfinite() infinities}. * {@link Double#isInfinite() infinities} unless this writer is lenient. * @return this writer. */ public JsonWriter value(double value) throws IOException { if (Double.isNaN(value) || Double.isInfinite(value)) { if (!lenient && (Double.isNaN(value) || Double.isInfinite(value))) { throw new IllegalArgumentException("Numeric values must be finite, but was " + value); } beforeValue(false); Loading @@ -329,6 +354,28 @@ public final class JsonWriter implements Closeable { return this; } /** * Encodes {@code value}. * * @param value a finite value. May not be {@link Double#isNaN() NaNs} or * {@link Double#isInfinite() infinities} unless this writer is lenient. * @return this writer. */ public JsonWriter value(Number value) throws IOException { if (value == null) { return nullValue(); } String string = value.toString(); if (!lenient && (string.equals("-Infinity") || string.equals("Infinity") || string.equals("NaN"))) { throw new IllegalArgumentException("Numeric values must be finite, but was " + value); } beforeValue(false); out.append(string); return this; } /** * Ensures all buffered data is written to the underlying {@link Writer} * and flushes that writer. Loading Loading @@ -364,7 +411,6 @@ public final class JsonWriter implements Closeable { switch (c) { case '"': case '\\': case '/': out.write('\\'); out.write(c); break; Loading Loading @@ -439,7 +485,7 @@ public final class JsonWriter implements Closeable { private void beforeValue(boolean root) throws IOException { switch (peek()) { case EMPTY_DOCUMENT: // first in document if (!root) { if (!lenient && !root) { throw new IllegalStateException( "JSON must start with an array or an object."); } Loading core/java/android/util/MalformedJsonException.java 0 → 100644 +31 −0 Original line number Diff line number Diff line /* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.util; import java.io.IOException; /** * Thrown when a reader encounters malformed JSON. Some syntax errors can be * ignored by calling {@link JsonReader#setLenient(boolean)}. */ public final class MalformedJsonException extends IOException { private static final long serialVersionUID = 1L; public MalformedJsonException(String message) { super(message); } } core/tests/coretests/src/android/util/JsonReaderTest.java +49 −4 Original line number Diff line number Diff line Loading @@ -16,11 +16,10 @@ package android.util; import java.util.Arrays; import junit.framework.TestCase; import java.io.IOException; import java.io.StringReader; import java.util.Arrays; import junit.framework.TestCase; public final class JsonReaderTest extends TestCase { Loading Loading @@ -677,7 +676,7 @@ public final class JsonReaderTest extends TestCase { try { reader.nextString(); fail(); } catch (IOException expected) { } catch (MalformedJsonException expected) { } } Loading Loading @@ -811,4 +810,50 @@ public final class JsonReaderTest extends TestCase { reader.nextNull(); reader.endArray(); } public void testStrictMultipleTopLevelValues() throws IOException { JsonReader reader = new JsonReader(new StringReader("[] []")); reader.beginArray(); reader.endArray(); try { reader.peek(); fail(); } catch (IOException expected) { } } public void testLenientMultipleTopLevelValues() throws IOException { JsonReader reader = new JsonReader(new StringReader("[] true {}")); reader.setLenient(true); reader.beginArray(); reader.endArray(); assertEquals(true, reader.nextBoolean()); reader.beginObject(); reader.endObject(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testStrictTopLevelValueType() { JsonReader reader = new JsonReader(new StringReader("true")); try { reader.nextBoolean(); fail(); } catch (IOException expected) { } } public void testLenientTopLevelValueType() throws IOException { JsonReader reader = new JsonReader(new StringReader("true")); reader.setLenient(true); assertEquals(true, reader.nextBoolean()); } public void testStrictNonExecutePrefix() { JsonReader reader = new JsonReader(new StringReader(")]}'\n []")); try { reader.beginArray(); fail(); } catch (IOException expected) { } } } Loading
api/current.xml +70 −16 Original line number Diff line number Diff line Loading @@ -198616,6 +198616,17 @@ <exception name="IOException" type="java.io.IOException"> </exception> </method> <method name="isLenient" return="boolean" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="nextBoolean" return="boolean" abstract="false" Loading Loading @@ -198746,21 +198757,6 @@ <exception name="IOException" type="java.io.IOException"> </exception> </method> <method name="syntaxError" return="java.io.IOException" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="message" type="java.lang.String"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> </method> </class> <class name="JsonToken" extends="java.lang.Enum" Loading Loading @@ -198893,6 +198889,17 @@ <exception name="IOException" type="java.io.IOException"> </exception> </method> <method name="isLenient" return="boolean" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="name" return="android.util.JsonWriter" abstract="false" Loading Loading @@ -198934,6 +198941,19 @@ <parameter name="indent" type="java.lang.String"> </parameter> </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="value" return="android.util.JsonWriter" abstract="false" Loading Loading @@ -198994,6 +199014,21 @@ <exception name="IOException" type="java.io.IOException"> </exception> </method> <method name="value" return="android.util.JsonWriter" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="value" type="java.lang.Number"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> </method> </class> <class name="Log" extends="java.lang.Object" Loading Loading @@ -199373,6 +199408,25 @@ </parameter> </method> </class> <class name="MalformedJsonException" extends="java.io.IOException" abstract="false" static="false" final="true" deprecated="not deprecated" visibility="public" > <constructor name="MalformedJsonException" type="android.util.MalformedJsonException" static="false" final="false" deprecated="not deprecated" visibility="public" > <parameter name="message" type="java.lang.String"> </parameter> </constructor> </class> <class name="MonthDisplayHelper" extends="java.lang.Object" abstract="false" Loading Loading @@ -258003,7 +258057,7 @@ deprecated="not deprecated" visibility="public" > <parameter name="t" type="T"> <parameter name="arg0" type="T"> </parameter> </method> </interface>
core/java/android/util/JsonReader.java +21 −13 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.util; import java.io.EOFException; import java.io.IOException; import java.io.Reader; import java.io.Closeable; Loading Loading @@ -248,6 +249,13 @@ public final class JsonReader implements Closeable { this.lenient = lenient; } /** * Returns true if this parser is liberal in what it accepts. */ public boolean isLenient() { return lenient; } /** * Consumes the next token from the JSON stream and asserts that it is the * beginning of a new array. Loading Loading @@ -311,7 +319,7 @@ public final class JsonReader implements Closeable { case EMPTY_DOCUMENT: replaceTop(JsonScope.NONEMPTY_DOCUMENT); JsonToken firstToken = nextValue(); if (token != JsonToken.BEGIN_ARRAY && token != JsonToken.BEGIN_OBJECT) { if (!lenient && token != JsonToken.BEGIN_ARRAY && token != JsonToken.BEGIN_OBJECT) { throw new IOException( "Expected JSON document to start with '[' or '{' but was " + token); } Loading @@ -327,7 +335,15 @@ public final class JsonReader implements Closeable { case NONEMPTY_OBJECT: return nextInObject(false); case NONEMPTY_DOCUMENT: return token = JsonToken.END_DOCUMENT; try { JsonToken token = nextValue(); if (lenient) { return token; } throw syntaxError("Expected EOF"); } catch (EOFException e) { return token = JsonToken.END_DOCUMENT; // TODO: avoid throwing here? } case CLOSED: throw new IllegalStateException("JsonReader is closed"); default: Loading Loading @@ -758,7 +774,7 @@ public final class JsonReader implements Closeable { } } throw syntaxError("End of input"); throw new EOFException("End of input"); } private void checkLenient() throws IOException { Loading Loading @@ -1030,8 +1046,6 @@ public final class JsonReader implements Closeable { * form -12.34e+56. Fractional and exponential parts are optional. Leading * zeroes are not allowed in the value or exponential part, but are allowed * in the fraction. * * <p>This has a side effect of setting isInteger. */ private JsonToken decodeNumber(char[] chars, int offset, int length) { int i = offset; Loading Loading @@ -1085,8 +1099,8 @@ public final class JsonReader implements Closeable { * Throws a new IO exception with the given message and a context snippet * with this reader's content. */ public IOException syntaxError(String message) throws IOException { throw new JsonSyntaxException(message + " near " + getSnippet()); private IOException syntaxError(String message) throws IOException { throw new MalformedJsonException(message + " near " + getSnippet()); } private CharSequence getSnippet() { Loading @@ -1097,10 +1111,4 @@ public final class JsonReader implements Closeable { snippet.append(buffer, pos, afterPos); return snippet; } private static class JsonSyntaxException extends IOException { private JsonSyntaxException(String s) { super(s); } } }
core/java/android/util/JsonWriter.java +50 −4 Original line number Diff line number Diff line Loading @@ -138,6 +138,8 @@ public final class JsonWriter implements Closeable { */ private String separator = ":"; private boolean lenient; /** * Creates a new instance that writes a JSON-encoded stream to {@code out}. * For best performance, ensure {@link Writer} is buffered; wrapping in Loading Loading @@ -168,6 +170,29 @@ public final class JsonWriter implements Closeable { } } /** * Configure this writer to relax its syntax rules. By default, this writer * only emits well-formed JSON as specified by <a * href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>. Setting the writer * to lenient permits the following: * <ul> * <li>Top-level values of any type. With strict writing, the top-level * value must be an object or an array. * <li>Numbers may be {@link Double#isNaN() NaNs} or {@link * Double#isInfinite() infinities}. * </ul> */ public void setLenient(boolean lenient) { this.lenient = lenient; } /** * Returns true if this writer has relaxed syntax rules. */ public boolean isLenient() { return lenient; } /** * Begins encoding a new array. Each call to this method must be paired with * a call to {@link #endArray}. Loading Loading @@ -306,11 +331,11 @@ public final class JsonWriter implements Closeable { * Encodes {@code value}. * * @param value a finite value. May not be {@link Double#isNaN() NaNs} or * {@link Double#isInfinite() infinities}. * {@link Double#isInfinite() infinities} unless this writer is lenient. * @return this writer. */ public JsonWriter value(double value) throws IOException { if (Double.isNaN(value) || Double.isInfinite(value)) { if (!lenient && (Double.isNaN(value) || Double.isInfinite(value))) { throw new IllegalArgumentException("Numeric values must be finite, but was " + value); } beforeValue(false); Loading @@ -329,6 +354,28 @@ public final class JsonWriter implements Closeable { return this; } /** * Encodes {@code value}. * * @param value a finite value. May not be {@link Double#isNaN() NaNs} or * {@link Double#isInfinite() infinities} unless this writer is lenient. * @return this writer. */ public JsonWriter value(Number value) throws IOException { if (value == null) { return nullValue(); } String string = value.toString(); if (!lenient && (string.equals("-Infinity") || string.equals("Infinity") || string.equals("NaN"))) { throw new IllegalArgumentException("Numeric values must be finite, but was " + value); } beforeValue(false); out.append(string); return this; } /** * Ensures all buffered data is written to the underlying {@link Writer} * and flushes that writer. Loading Loading @@ -364,7 +411,6 @@ public final class JsonWriter implements Closeable { switch (c) { case '"': case '\\': case '/': out.write('\\'); out.write(c); break; Loading Loading @@ -439,7 +485,7 @@ public final class JsonWriter implements Closeable { private void beforeValue(boolean root) throws IOException { switch (peek()) { case EMPTY_DOCUMENT: // first in document if (!root) { if (!lenient && !root) { throw new IllegalStateException( "JSON must start with an array or an object."); } Loading
core/java/android/util/MalformedJsonException.java 0 → 100644 +31 −0 Original line number Diff line number Diff line /* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.util; import java.io.IOException; /** * Thrown when a reader encounters malformed JSON. Some syntax errors can be * ignored by calling {@link JsonReader#setLenient(boolean)}. */ public final class MalformedJsonException extends IOException { private static final long serialVersionUID = 1L; public MalformedJsonException(String message) { super(message); } }
core/tests/coretests/src/android/util/JsonReaderTest.java +49 −4 Original line number Diff line number Diff line Loading @@ -16,11 +16,10 @@ package android.util; import java.util.Arrays; import junit.framework.TestCase; import java.io.IOException; import java.io.StringReader; import java.util.Arrays; import junit.framework.TestCase; public final class JsonReaderTest extends TestCase { Loading Loading @@ -677,7 +676,7 @@ public final class JsonReaderTest extends TestCase { try { reader.nextString(); fail(); } catch (IOException expected) { } catch (MalformedJsonException expected) { } } Loading Loading @@ -811,4 +810,50 @@ public final class JsonReaderTest extends TestCase { reader.nextNull(); reader.endArray(); } public void testStrictMultipleTopLevelValues() throws IOException { JsonReader reader = new JsonReader(new StringReader("[] []")); reader.beginArray(); reader.endArray(); try { reader.peek(); fail(); } catch (IOException expected) { } } public void testLenientMultipleTopLevelValues() throws IOException { JsonReader reader = new JsonReader(new StringReader("[] true {}")); reader.setLenient(true); reader.beginArray(); reader.endArray(); assertEquals(true, reader.nextBoolean()); reader.beginObject(); reader.endObject(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testStrictTopLevelValueType() { JsonReader reader = new JsonReader(new StringReader("true")); try { reader.nextBoolean(); fail(); } catch (IOException expected) { } } public void testLenientTopLevelValueType() throws IOException { JsonReader reader = new JsonReader(new StringReader("true")); reader.setLenient(true); assertEquals(true, reader.nextBoolean()); } public void testStrictNonExecutePrefix() { JsonReader reader = new JsonReader(new StringReader(")]}'\n []")); try { reader.beginArray(); fail(); } catch (IOException expected) { } } }