JsonReader

Reads a JSON (RFC 7159) encoded value as a stream of tokens. This stream includes both literal values (strings, numbers, booleans, and nulls) as well as the begin and end delimiters of objects and arrays. The tokens are traversed in depth-first order, the same order that they appear in the JSON document. Within JSON objects, name/value pairs are represented by a single token.

Parsing JSON To create a recursive descent parser for your own JSON streams, first create an entry point method that creates a {@code JsonReader} .

Next, create handler methods for each structure in your JSON text. You'll need a method for each object type and for each array type.

  • Within array handling methods, first call beginArray to consume the array's opening bracket. Then create a while loop that accumulates values, terminating when hasNext is false. Finally, read the array's closing bracket by calling .
  • Within object handling methods, first call beginObject to consume the object's opening brace. Then create a while loop that assigns values to local variables based on their name. This loop should terminate when hasNext is false. Finally, read the object's closing brace by calling endObject .

When a nested object or array is encountered, delegate to the corresponding handler method.

When an unknown name is encountered, strict parsers should fail with an exception. Lenient parsers should call skipValue to recursively skip the value's nested tokens, which may otherwise conflict.

If a value may be null, you should first check using peek . Null literals can be consumed using either nextNull or skipValue .

Example Suppose we'd like to parse a stream of messages such as the following:
{@code * [ * { * "id": 912345678901, * "text": "How do I read a JSON stream in Java?", * "geo": null, * "user": { * "name": "json_newb", * "followers_count": 41 * } * }, * { * "id": 912345678902, * "text": "@json_newb just use JsonReader!", * "geo": [50.454722, -104.606667], * "user": { * "name": "jesse", * "followers_count": 2 * } * } * ] * }
This code implements the parser for the above structure:
{@code * public ListreadJsonStream(BufferedSource source) throws IOException {
 *   JsonReader reader = JsonReader.of(source);
 *   try {
 *     return readMessagesArray(reader);
 *   } finally {
 *     reader.close();
 *   }
 * }
 *
 * public List
Number Handling This reader permits numeric values to be read as strings and string values to be read as numbers. For example, both elements of the JSON array {@code [1, "1"]} may be read using either or nextString . This behavior is intended to prevent lossy numeric conversions: double is JavaScript's only numeric type and very large values like {@code 9007199254740993} cannot be represented exactly on that platform. To minimize precision loss, extremely large values should be written and read as strings in JSON.

Each {@code JsonReader} may be used to read a single JSON stream. Instances of this class are not thread safe.

abstract class JsonReader : Closeable

Constructors

JsonReader
Link copied to clipboard
open fun JsonReader()
JsonReader
Link copied to clipboard
open fun JsonReader(copyFrom: JsonReader)

Types

Options
Link copied to clipboard

A set of strings to be chosen with selectName or selectString . This prepares the encoded values of the strings so they can be read directly from the input source.

class Options
Token
Link copied to clipboard

A structure, name, or value type in a JSON-encoded string.

enum Token

Functions

beginArray
Link copied to clipboard

Consumes the next token from the JSON stream and asserts that it is the beginning of a new array.

abstract fun beginArray()
beginObject
Link copied to clipboard

Consumes the next token from the JSON stream and asserts that it is the beginning of a new object.

abstract fun beginObject()
close
Link copied to clipboard
abstract fun close()
endArray
Link copied to clipboard

Consumes the next token from the JSON stream and asserts that it is the end of the current array.

abstract fun endArray()
endObject
Link copied to clipboard

Consumes the next token from the JSON stream and asserts that it is the end of the current object.

abstract fun endObject()
failOnUnknown
Link copied to clipboard

Returns true if this parser forbids skipping names and values.

fun failOnUnknown(): Boolean
getPath
Link copied to clipboard

Returns a JsonPath to the current location in the JSON value.

fun getPath(): String
hasNext
Link copied to clipboard

Returns true if the current array or object has another element.

abstract fun hasNext(): Boolean
isLenient
Link copied to clipboard

Returns true if this parser is liberal in what it accepts.

fun isLenient(): Boolean
nextBoolean
Link copied to clipboard

Returns the boolean value of the next token, consuming it.

abstract fun nextBoolean(): Boolean
nextDouble
Link copied to clipboard

Returns the double value of the next token, consuming it. If the next token is a string, this method will attempt to parse it as a double using .

abstract fun nextDouble(): Double
nextInt
Link copied to clipboard

Returns the int value of the next token, consuming it. If the next token is a string, this method will attempt to parse it as an int. If the next token's numeric value cannot be exactly represented by a Java {@code int} , this method throws.

abstract fun nextInt(): Int
nextLong
Link copied to clipboard

Returns the long value of the next token, consuming it. If the next token is a string, this method will attempt to parse it as a long. If the next token's numeric value cannot be exactly represented by a Java {@code long} , this method throws.

abstract fun nextLong(): Long
nextName
Link copied to clipboard

Returns the next token, a property name , and consumes it.

abstract fun nextName(): String
nextNull
Link copied to clipboard

Consumes the next token from the JSON stream and asserts that it is a literal null. Returns null.

abstract fun <T> nextNull(): T
nextSource
Link copied to clipboard

Returns the next value as a stream of UTF-8 bytes and consumes it.

The following program demonstrates how JSON bytes are returned from an enclosing stream as their original bytes, including their original whitespace:

{@code * String json = "{\"a\": [4, 5 ,6.0, {\"x\":7}, 8], \"b\": 9}"; * JsonReader reader = JsonReader.of(new Buffer().writeUtf8(json)); * reader.beginObject(); * assertThat(reader.nextName()).isEqualTo("a"); * try (BufferedSource bufferedSource = reader.valueSource()) { * assertThat(bufferedSource.readUtf8()).isEqualTo("[4, 5 ,6.0, {\"x\":7}, 8]"); * } * assertThat(reader.nextName()).isEqualTo("b"); * assertThat(reader.nextInt()).isEqualTo(9); * reader.endObject(); * }

This reads an entire value: composite objects like arrays and objects are returned in their entirety. The stream starts with the first character of the value (typically {@code [} , { , or {@code "} ) and ends with the last character of the object (typically {@code ]} , } , or {@code "} ).

The returned source may not be used after any other method on this {@code JsonReader} is called. For example, the following code crashes with an exception:

{@code * JsonReader reader = ... * reader.beginArray(); * BufferedSource source = reader.valueSource(); * reader.endArray(); * source.readUtf8(); // Crash! * }

The returned bytes are not validated. This method assumes the stream is well-formed JSON and only attempts to find the value's boundary in the byte stream. It is the caller's responsibility to check that the returned byte stream is a valid JSON value.

Closing the returned source does not close this reader.

abstract fun nextSource(): BufferedSource
nextString
Link copied to clipboard

Returns the string value of the next token, consuming it. If the next token is a number, this method will return its string form.

abstract fun nextString(): String
of
Link copied to clipboard

Returns a new instance that reads UTF-8 encoded JSON from {@code source} .

open fun of(source: BufferedSource): JsonReader
peek
Link copied to clipboard

Returns the type of the next token without consuming it.

abstract fun peek(): JsonReader.Token
peekJson
Link copied to clipboard

Returns a new {@code JsonReader} that can read data from this {@code JsonReader} without consuming it. The returned reader becomes invalid once this one is next read or closed.

For example, we can use {@code peekJson()} to lookahead and read the same data multiple times.

{@code * Buffer buffer = new Buffer(); * buffer.writeUtf8("[123, 456, 789]") * * JsonReader jsonReader = JsonReader.of(buffer); * jsonReader.beginArray(); * jsonReader.nextInt(); // Returns 123, reader contains 456, 789 and ]. * * JsonReader peek = reader.peekJson(); * peek.nextInt() // Returns 456. * peek.nextInt() // Returns 789. * peek.endArray() * * jsonReader.nextInt() // Returns 456, reader contains 789 and ]. * }

abstract fun peekJson(): JsonReader
promoteNameToValue
Link copied to clipboard

Changes the reader to treat the next name as a string value. This is useful for map adapters so that arbitrary type adapters can use nextString to read a name value.

In this example, calling this method allows two sequential calls to nextString :

{@code * JsonReader reader = JsonReader.of(new Buffer().writeUtf8("{\"a\":\"b\"}")); * reader.beginObject(); * reader.promoteNameToValue(); * assertEquals("a", reader.nextString()); * assertEquals("b", reader.nextString()); * reader.endObject(); * }

abstract fun promoteNameToValue()
pushScope
Link copied to clipboard
fun pushScope(newTop: Int)
readJsonValue
Link copied to clipboard

Returns the value of the next token, consuming it. The result may be a string, number, boolean, null, map, or list, according to the JSON structure.

fun readJsonValue(): Any
selectName
Link copied to clipboard

If the next token is a property name that's in {@code options} , this consumes it and returns its index. Otherwise this returns -1 and no name is consumed.

abstract fun selectName(options: JsonReader.Options): Int
selectString
Link copied to clipboard

If the next token is a string that's in {@code options} , this consumes it and returns its index. Otherwise this returns -1 and no string is consumed.

abstract fun selectString(options: JsonReader.Options): Int
setTag
Link copied to clipboard

Assigns the tag value using the given class key and value.

fun <T> setTag(clazz: Class<T>, value: T)
skipName
Link copied to clipboard

Skips the next token, consuming it. This method is intended for use when the JSON token stream contains unrecognized or unhandled names.

This throws a JsonDataException if this parser has been configured to names.

abstract fun skipName()
skipValue
Link copied to clipboard

Skips the next value recursively. If it is an object or array, all nested elements are skipped. This method is intended for use when the JSON token stream contains unrecognized or unhandled values.

This throws a JsonDataException if this parser has been configured to values.

abstract fun skipValue()
syntaxError
Link copied to clipboard

Throws a new IO exception with the given message and a context snippet with this reader's content.

fun syntaxError(message: String): JsonEncodingException
tag
Link copied to clipboard

Returns the tag value for the given class key.

fun <T> tag(clazz: Class<T>): T
typeMismatch
Link copied to clipboard
fun typeMismatch(value: Any, expected: Any): JsonDataException

Properties

failOnUnknown
Link copied to clipboard

True to throw a JsonDataException on any attempt to call skipValue .

open var failOnUnknown: Boolean
lenient
Link copied to clipboard

True to accept non-spec compliant JSON.

open var lenient: Boolean
pathIndices
Link copied to clipboard
open val pathIndices: Array<Int>
pathNames
Link copied to clipboard
open val pathNames: Array<String>
scopes
Link copied to clipboard
open val scopes: Array<Int>
stackSize
Link copied to clipboard
open val stackSize: Int

Inheritors

JsonUtf8Reader
Link copied to clipboard
JsonValueReader
Link copied to clipboard