Java tutorial
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2011-2017 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * https://oss.oracle.com/licenses/CDDL+GPL-1.1 * or LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package javax.json.stream; import java.io.Closeable; import java.math.BigDecimal; import java.util.stream.Stream; import java.util.Map; import javax.json.JsonValue; import javax.json.JsonObject; import javax.json.JsonArray; /** * Provides forward, read-only access to JSON data in a streaming way. This * is the most efficient way for reading JSON data. * This is the only way to parse and process JSON data that are too big to be loaded in memory. * <p>The class * {@link javax.json.Json} contains methods to create parsers from input * sources ({@link java.io.InputStream} and {@link java.io.Reader}). * * <p> * The following example demonstrates how to create a parser from a string * that contains an empty JSON array: * <pre> * <code> * JsonParser parser = Json.createParser(new StringReader("[]")); * </code> * </pre> * * <p> * The class {@link JsonParserFactory} also contains methods to create * {@code JsonParser} instances. {@link JsonParserFactory} is preferred * when creating multiple parser instances. A sample usage is shown * in the following example: * <pre> * <code> * JsonParserFactory factory = Json.createParserFactory(); * JsonParser parser1 = factory.createParser(...); * JsonParser parser2 = factory.createParser(...); * </code> * </pre> * * <p> * {@code JsonParser} parses JSON using the pull parsing programming model. * In this model the client code controls the thread and calls the method * {@code next()} to advance the parser to the next state after * processing each element. The parser can generate the following events: * {@code START_OBJECT}, {@code END_OBJECT}, {@code START_ARRAY}, * {@code END_ARRAY}, {@code KEY_NAME}, {@code VALUE_STRING}, * {@code VALUE_NUMBER}, {@code VALUE_TRUE}, {@code VALUE_FALSE}, * and {@code VALUE_NULL}. * * <p> * <b>For example</b>, for an empty JSON object ({ }), the parser generates the event * {@code START_OBJECT} with the first call to the method {@code next()} and the * event {@code END_OBJECT} with the second call to the method {@code next()}. * The following code demonstrates how to access these events: * * <pre> * <code> * Event event = parser.next(); // START_OBJECT * event = parser.next(); // END_OBJECT * </code> * </pre> * * <p> * <b>For example</b>, for the following JSON: * <pre> * { * "firstName": "John", "lastName": "Smith", "age": 25, * "phoneNumber": [ * { "type": "home", "number": "212 555-1234" }, * { "type": "fax", "number": "646 555-4567" } * ] * } * </pre> * * <p>calls to the method {@code next()} result in parse events at the specified * locations below (marked in bold): * * <pre> * {<B>START_OBJECT</B> * "firstName"<B>KEY_NAME</B>: "John"<B>VALUE_STRING</B>, "lastName"<B>KEY_NAME</B>: "Smith"<B>VALUE_STRING</B>, "age"<B>KEY_NAME</B>: 25<B>VALUE_NUMBER</B>, * "phoneNumber"<B>KEY_NAME</B> : [<B>START_ARRAY</B> * {<B>START_OBJECT</B> "type"<B>KEY_NAME</B>: "home"<B>VALUE_STRING</B>, "number"<B>KEY_NAME</B>: "212 555-1234"<B>VALUE_STRING</B> }<B>END_OBJECT</B>, * {<B>START_OBJECT</B> "type"<B>KEY_NAME</B>: "fax"<B>VALUE_STRING</B>, "number"<B>KEY_NAME</B>: "646 555-4567"<B>VALUE_STRING</B> }<B>END_OBJECT</B> * ]<B>END_ARRAY</B> * }<B>END_OBJECT</B> * </pre> * * The methods {@link #next()} and {@link #hasNext()} enable iteration over * parser events to process JSON data. {@code JsonParser} provides get methods * to obtain the value at the current state of the parser. For example, the * following code shows how to obtain the value "John" from the JSON above: * * <pre> * <code> * Event event = parser.next(); // START_OBJECT * event = parser.next(); // KEY_NAME * event = parser.next(); // VALUE_STRING * parser.getString(); // "John" * </code> * </pre> * * Starting in version 1.1, it is possible to build a partial JSON object * model from the stream, at the current parser position. * The methods {@link #getArray} and {@link #getObject} can be used to read in * a {@code JsonArray} or {@code JsonObject}. For example, the following code * shows how to obtain the phoneNumber in a JsonArray, from the JSON above: * * <pre><code> * while (parser.hasNext() { * Event event = parser.next(); * if (event == JsonParser.Event.KEY_NAME ) { * String key = getString(); * event = parser.next(); * if (key.equals("phoneNumber") { * JsonArray phones = parser.getArray(); * } * } * } * </code></pre> * * The methods {@link #getArrayStream} and {@link #getObjectStream} can be used * to get a stream of the elements of a {@code JsonArray} or {@code JsonObject}. * For example, the following code shows another way to obtain John's phoneNumber * in a {@code JsonArray} : * * <pre>{@code * Event event = parser.next(); // START_OBJECT * JsonArray phones = (JsonArray) * parser.getObjectStream().filter(e->e.getKey().equals("phoneNumber")) * .map(e->e.getValue()) * .findFirst() * .get(); * }</pre> * * The methods {@link #skipArray} and {@link #skipObject} can be used to * skip tokens and position the parser to {@code END_ARRAY} or * {@code END_OBJECT}. * <p> * {@code JsonParser} can be used to parse sequence of JSON values that are not * enclosed in a JSON array, e.g. { } { }. The following code demonstrates how * to parse such sequence. * <pre><code> * JsonParser parser = Json.createParser(...); * while (parser.hasNext) { * parser.next(); // advance parser state * JsonValue value = parser.getValue(); * } * </code></pre> * * @see javax.json.Json * @see JsonParserFactory */ public interface JsonParser extends /*Auto*/Closeable { /** * An event from {@code JsonParser}. */ enum Event { /** * Start of a JSON array. The position of the parser is after '['. */ START_ARRAY, /** * Start of a JSON object. The position of the parser is after '{'. */ START_OBJECT, /** * Name in a name/value pair of a JSON object. The position of the parser * is after the key name. The method {@link #getString} returns the key * name. */ KEY_NAME, /** * String value in a JSON array or object. The position of the parser is * after the string value. The method {@link #getString} * returns the string value. */ VALUE_STRING, /** * Number value in a JSON array or object. The position of the parser is * after the number value. {@code JsonParser} provides the following * methods to access the number value: {@link #getInt}, * {@link #getLong}, and {@link #getBigDecimal}. */ VALUE_NUMBER, /** * {@code true} value in a JSON array or object. The position of the * parser is after the {@code true} value. */ VALUE_TRUE, /** * {@code false} value in a JSON array or object. The position of the * parser is after the {@code false} value. */ VALUE_FALSE, /** * {@code null} value in a JSON array or object. The position of the * parser is after the {@code null} value. */ VALUE_NULL, /** * End of a JSON object. The position of the parser is after '}'. */ END_OBJECT, /** * End of a JSON array. The position of the parser is after ']'. */ END_ARRAY } /** * Returns {@code true} if there are more parsing states. This method returns * {@code false} if the parser reaches the end of the JSON text. * * @return {@code true} if there are more parsing states. * @throws javax.json.JsonException if an i/o error occurs (IOException * would be cause of JsonException) * @throws JsonParsingException if the parser encounters invalid JSON * when advancing to next state. */ boolean hasNext(); /** * Returns the event for the next parsing state. * * @throws javax.json.JsonException if an i/o error occurs (IOException * would be cause of JsonException) * @throws JsonParsingException if the parser encounters invalid JSON * when advancing to next state. * @throws java.util.NoSuchElementException if there are no more parsing * states. * @return the event for the next parsing state */ Event next(); /** * Returns a {@code String} for the name in a name/value pair, * for a string value or a number value. This method should only be called * when the parser state is {@link Event#KEY_NAME}, {@link Event#VALUE_STRING}, * or {@link Event#VALUE_NUMBER}. * * @return a name when the parser state is {@link Event#KEY_NAME} * a string value when the parser state is {@link Event#VALUE_STRING} * a number value when the parser state is {@link Event#VALUE_NUMBER} * @throws IllegalStateException when the parser state is not * {@code KEY_NAME}, {@code VALUE_STRING}, or {@code VALUE_NUMBER} */ String getString(); /** * Returns true if the JSON number at the current parser state is a * integral number. A {@link BigDecimal} may be used to store the value * internally and this method semantics are defined using its * {@code scale()}. If the scale is zero, then it is considered integral * type. This integral type information can be used to invoke an * appropriate accessor method to obtain a numeric value as in the * following example: * * <pre> * <code> * JsonParser parser = ... * if (parser.isIntegralNumber()) { * parser.getInt(); // or other methods to get integral value * } else { * parser.getBigDecimal(); * } * </code> * </pre> * * @return true if this number is a integral number, otherwise false * @throws IllegalStateException when the parser state is not * {@code VALUE_NUMBER} */ boolean isIntegralNumber(); /** * Returns a JSON number as an integer. The returned value is equal * to {@code new BigDecimal(getString()).intValue()}. Note that * this conversion can lose information about the overall magnitude * and precision of the number value as well as return a result with * the opposite sign. This method should only be called when the parser * state is {@link Event#VALUE_NUMBER}. * * @return an integer for a JSON number * @throws IllegalStateException when the parser state is not * {@code VALUE_NUMBER} * @see java.math.BigDecimal#intValue() */ int getInt(); /** * Returns a JSON number as a long. The returned value is equal * to {@code new BigDecimal(getString()).longValue()}. Note that this * conversion can lose information about the overall magnitude and * precision of the number value as well as return a result with * the opposite sign. This method is only called when the parser state is * {@link Event#VALUE_NUMBER}. * * @return a long for a JSON number * @throws IllegalStateException when the parser state is not * {@code VALUE_NUMBER} * @see java.math.BigDecimal#longValue() */ long getLong(); /** * Returns a JSON number as a {@code BigDecimal}. The {@code BigDecimal} * is created using {@code new BigDecimal(getString())}. This * method should only called when the parser state is * {@link Event#VALUE_NUMBER}. * * @return a {@code BigDecimal} for a JSON number * @throws IllegalStateException when the parser state is not * {@code VALUE_NUMBER} */ BigDecimal getBigDecimal(); /** * Return the location that corresponds to the parser's current state in * the JSON input source. The location information is only valid in the * current parser state (or until the parser is advanced to a next state). * * @return a non-null location corresponding to the current parser state * in JSON input source */ JsonLocation getLocation(); /** * Returns a {@code JsonObject} and advances the parser to the * corresponding {@code END_OBJECT}. * * @return the {@code JsonObject} at the current parser position * * @throws IllegalStateException when the parser state is not * {@code START_OBJECT} * * @since 1.1 */ default public JsonObject getObject() { throw new UnsupportedOperationException(); } /** * Returns a {@code JsonValue} at the current parser position. * If the parser state is {@code START_ARRAY}, the behavior is * the same as {@link #getArray}. If the parser state is * {@code START_OBJECT}, the behavior is the same as * {@link #getObject}. For all other cases, if applicable, the JSON value is * read and returned. * * @return the {@code JsonValue} at the current parser position. * @throws IllegalStateException when the parser state is * {@code END_OBJECT} or {@code END_ARRAY} * * @since 1.1 */ default public JsonValue getValue() { throw new UnsupportedOperationException(); } /** * Returns a {@code JsonArray} and advance the parser to the * the corresponding {@code END_ARRAY}. * * @return the {@code JsonArray} at the current parser position * * @throws IllegalStateException when the parser state is not * {@code START_ARRAY} * * @since 1.1 */ default public JsonArray getArray() { throw new UnsupportedOperationException(); } /** * Returns a stream of the {@code JsonArray} elements. * The parser state must be {@code START_ARRAY}. * The elements are read lazily, on an as-needed basis, as * required by the stream operations. * If the stream operations do not consume * all of the array elements, {@link skipArray} can be used to * skip the unprocessed array elements. * * @return a stream of elements of the {@code JsonArray} * * @throws IllegalStateException when the parser state is not * {@code START_ARRAY} * * @since 1.1 */ default public Stream<JsonValue> getArrayStream() { throw new UnsupportedOperationException(); } /** * Returns a stream of the {@code JsonObject}'s * name/value pairs. The parser state must be {@code START_OBJECT}. * The name/value pairs are read lazily, on an as-needed basis, as * required by the stream operations. * If the stream operations do not consume * all of the object's name/value pairs, {@link skipObject} can be * used to skip the unprocessed elements. * * @return a stream of name/value pairs of the {@code JsonObject} * * @throws IllegalStateException when the parser state is not * {@code START_OBJECT} * * @since 1.1 */ default public Stream<Map.Entry<String, JsonValue>> getObjectStream() { throw new UnsupportedOperationException(); } /** * Returns a stream of {@code JsonValue} from a sequence of * JSON values. The values are read lazily, on an as-needed basis, * as needed by the stream operations. * * @return a Stream of {@code JsonValue} * * @throws IllegalStateException if the parser is in an array or object. * * @since 1.1 */ default public Stream<JsonValue> getValueStream() { throw new UnsupportedOperationException(); } /** * Advance the parser to {@code END_ARRAY}. * If the parser is in array context, i.e. it has previously * encountered a {@code START_ARRAY} without encountering the * corresponding {@code END_ARRAY}, the parser is advanced to * the corresponding {@code END_ARRAY}. * If the parser is not in any array context, nothing happens. * * @since 1.1 */ default public void skipArray() { throw new UnsupportedOperationException(); } /** * Advance the parser to {@code END_OBJECT}. * If the parser is in object context, i.e. it has previously * encountered a {@code START_OBJECT} without encountering the * corresponding {@code END_OBJECT}, the parser is advanced to * the corresponding {@code END_OBJECT}. * If the parser is not in any object context, nothing happens. * * @since 1.1 */ default public void skipObject() { throw new UnsupportedOperationException(); } /** * Closes this parser and frees any resources associated with the * parser. This method closes the underlying input source. * * @throws javax.json.JsonException if an i/o error occurs (IOException * would be cause of JsonException) */ @Override void close(); }