/* Jackson JSON-processor.
*
* Copyright (c) 2007- Tatu Saloranta, tatu.saloranta@iki.fi
*/
package divconq.json3;
import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import divconq.io.CharSequenceReader;
import divconq.json3.base.ReaderBasedJsonParser;
import divconq.json3.io.IOContext;
import divconq.json3.util.BufferRecycler;
/**
* Base class that defines public API for reading JSON content.
* Instances are created using factory methods of
* a instance.
*
* @author Tatu Saloranta
*/
public abstract class JsonParser implements Closeable
{
static public ReaderBasedJsonParser createParser(InputStream in) throws IOException {
IOContext ctx = new IOContext(new BufferRecycler(), in, false);
/* TODO maybe detect encoding someday
JsonEncoding enc = ctx.getEncoding();
Reader rdr = new InputStreamReader(in, enc.getJavaName());
*/
Reader rdr = new InputStreamReader(in, "UTF-8");
return new ReaderBasedJsonParser(ctx, rdr);
}
static public ReaderBasedJsonParser createParser(CharSequence in) throws IOException {
IOContext ctx = new IOContext(new BufferRecycler(), in, false);
CharSequenceReader rdr = new CharSequenceReader(in);
return new ReaderBasedJsonParser(ctx, rdr);
}
private final static int MIN_BYTE_I = (int) Byte.MIN_VALUE;
// as per [JACKSON-804], allow range up to and including 255
private final static int MAX_BYTE_I = (int) 255;
private final static int MIN_SHORT_I = (int) Short.MIN_VALUE;
private final static int MAX_SHORT_I = (int) Short.MAX_VALUE;
/**
* Enumeration of possible "native" (optimal) types that can be
* used for numbers.
*/
public enum NumberType {
INT, LONG, BIG_INTEGER, FLOAT, DOUBLE, BIG_DECIMAL
};
/**
* Enumeration that defines all on/off features for parsers.
*/
public enum Feature {
// // // Low-level I/O handling features:
/**
* Feature that determines whether parser will automatically
* close underlying input source that is NOT owned by the
* parser. If disabled, calling application has to separately
* close the underlying {@link InputStream} and {@link Reader}
* instances used to create the parser. If enabled, parser
* will handle closing, as long as parser itself gets closed:
* this happens when end-of-input is encountered, or parser
* is closed by a call to {@link JsonParser#close}.
*<p>
* Feature is enabled by default.
*/
AUTO_CLOSE_SOURCE(true),
// // // Support for non-standard data format constructs
/**
* Feature that determines whether parser will allow use
* of Java/C++ style comments (both '/'+'*' and
* '//' varieties) within parsed content or not.
*<p>
* Since JSON specification does not mention comments as legal
* construct,
* this is a non-standard feature; however, in the wild
* this is extensively used. As such, feature is
* <b>disabled by default</b> for parsers and must be
* explicitly enabled.
*/
ALLOW_COMMENTS(false),
/**
* Feature that determines whether parser will allow use
* of YAML comments, ones starting with '#' and continuing
* until the end of the line. This commenting style is common
* with scripting languages as well.
*<p>
* Since JSON specification does not mention comments as legal
* construct,
* this is a non-standard feature. As such, feature is
* <b>disabled by default</b> for parsers and must be
* explicitly enabled.
*/
ALLOW_YAML_COMMENTS(false),
/**
* Feature that determines whether parser will allow use
* of unquoted field names (which is allowed by Javascript,
* but not by JSON specification).
*<p>
* Since JSON specification requires use of double quotes for
* field names,
* this is a non-standard feature, and as such disabled by default.
*/
ALLOW_UNQUOTED_FIELD_NAMES(false),
/**
* Feature that determines whether parser will allow use
* of single quotes (apostrophe, character '\'') for
* quoting Strings (names and String values). If so,
* this is in addition to other acceptabl markers.
* but not by JSON specification).
*<p>
* Since JSON specification requires use of double quotes for
* field names,
* this is a non-standard feature, and as such disabled by default.
*/
ALLOW_SINGLE_QUOTES(false),
/**
* Feature that determines whether parser will allow
* JSON Strings to contain unquoted control characters
* (ASCII characters with value less than 32, including
* tab and line feed characters) or not.
* If feature is set false, an exception is thrown if such a
* character is encountered.
*<p>
* Since JSON specification requires quoting for all control characters,
* this is a non-standard feature, and as such disabled by default.
*/
ALLOW_UNQUOTED_CONTROL_CHARS(false),
/**
* Feature that can be enabled to accept quoting of all character
* using backslash qooting mechanism: if not enabled, only characters
* that are explicitly listed by JSON specification can be thus
* escaped (see JSON spec for small list of these characters)
*<p>
* Since JSON specification requires quoting for all control characters,
* this is a non-standard feature, and as such disabled by default.
*/
ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER(false),
/**
* Feature that determines whether parser will allow
* JSON integral numbers to start with additional (ignorable)
* zeroes (like: 000001). If enabled, no exception is thrown, and extra
* nulls are silently ignored (and not included in textual representation
* exposed via {@link JsonParser#getText}).
*<p>
* Since JSON specification does not allow leading zeroes,
* this is a non-standard feature, and as such disabled by default.
*/
ALLOW_NUMERIC_LEADING_ZEROS(false),
/**
* Feature that allows parser to recognize set of
* "Not-a-Number" (NaN) tokens as legal floating number
* values (similar to how many other data formats and
* programming language source code allows it).
* Specific subset contains values that
* <a href="http://www.w3.org/TR/xmlschema-2/">XML Schema</a>
* (see section 3.2.4.1, Lexical Representation)
* allows (tokens are quoted contents, not including quotes):
*<ul>
* <li>"INF" (for positive infinity), as well as alias of "Infinity"
* <li>"-INF" (for negative infinity), alias "-Infinity"
* <li>"NaN" (for other not-a-numbers, like result of division by zero)
*</ul>
*<p>
* Since JSON specification does not allow use of such values,
* this is a non-standard feature, and as such disabled by default.
*/
ALLOW_NON_NUMERIC_NUMBERS(false),
/**
* Feature that determines whether {@link JsonParser} will explicitly
* check that no duplicate JSON Object field names are encountered.
* If enabled, parser will check all names within context and report
* duplicates by throwing a {@link JsonParseException}; if disabled,
* parser will not do such checking. Assumption in latter case is
* that caller takes care of handling duplicates at a higher level:
* data-binding, for example, has features to specify detection to
* be done there.
*<p>
* Note that enabling this feature will incur performance overhead
* due to having to store and check additional information: this typically
* adds 20-30% to execution time for basic parsing.
*
* @since 2.3
*/
STRICT_DUPLICATE_DETECTION(false),
;
/**
* Whether feature is enabled or disabled by default.
*/
private final boolean _defaultState;
private final int _mask;
/*
* Method that calculates bit set (flags) of all features that
* are enabled by default.
*/
public static int collectDefaults()
{
int flags = 0;
for (Feature f : values()) {
if (f.enabledByDefault()) {
flags |= f.getMask();
}
}
return flags;
}
private Feature(boolean defaultState) {
_mask = (1 << ordinal());
_defaultState = defaultState;
}
public boolean enabledByDefault() { return _defaultState; }
/*
* @since 2.3
*/
public boolean enabledIn(int flags) { return (flags & _mask) != 0; }
public int getMask() { return (1 << ordinal()); }
}
/*
/**********************************************************
/* Minimal configuration state
/**********************************************************
*/
/*
/**********************************************************
/* Construction, configuration, initialization
/**********************************************************
*/
protected JsonParser() { }
/*
* Method that can be used to get access to object that is used
* to access input being parsed; this is usually either
* {@link InputStream} or {@link Reader}, depending on what
* parser was constructed with.
* Note that returned value may be null in some cases; including
* case where parser implementation does not want to exposed raw
* source to caller.
* In cases where input has been decorated, object returned here
* is the decorated version; this allows some level of interaction
* between users of parser and decorator object.
*<p>
* In general use of this accessor should be considered as
* "last effort", i.e. only used if no other mechanism is applicable.
*/
public Object getInputSource() { return null; }
/*
/**********************************************************
/* Format support
/**********************************************************
*/
/*
/**********************************************************
/* Capability introspection
/**********************************************************
*/
/*
* Method that can be called to determine if a custom
* {@link ObjectCodec} is needed for binding data parsed
* using {@link JsonParser} constructed by this factory
* (which typically also implies the same for serialization
* with {@link JsonGenerator}).
*
* @return True if custom codec is needed with parsers and
* generators created by this factory; false if a general
* {@link ObjectCodec} is enough
*
* @since 2.1
*/
public boolean requiresCustomCodec() { return false;}
/*
/**********************************************************
/* Closeable implementation
/**********************************************************
*/
/*
* Closes the parser so that no further iteration or data access
* can be made; will also close the underlying input source
* if parser either <b>owns</b> the input source, or feature
* {@link Feature#AUTO_CLOSE_SOURCE} is enabled.
* Whether parser owns the input source depends on factory
* method that was used to construct instance (so check
* {@link com.fasterxml.jackson.core.JsonFactory} for details,
* but the general
* idea is that if caller passes in closable resource (such
* as {@link InputStream} or {@link Reader}) parser does NOT
* own the source; but if it passes a reference (such as
* {@link java.io.File} or {@link java.net.URL} and creates
* stream or reader it does own them.
*/
@Override
public abstract void close() throws IOException;
/*
/**********************************************************
/* Buffer handling
/**********************************************************
*/
/*
* Method that can be called to push back any content that
* has been read but not consumed by the parser. This is usually
* done after reading all content of interest using parser.
* Content is released by writing it to given stream if possible;
* if underlying input is byte-based it can released, if not (char-based)
* it can not.
*
* @return -1 if the underlying content source is not byte based
* (that is, input can not be sent to {@link OutputStream};
* otherwise number of bytes released (0 if there was nothing to release)
*
* @throws IOException if write to stream threw exception
*/
public int releaseBuffered(OutputStream out) throws IOException {
return -1;
}
/*
* Method that can be called to push back any content that
* has been read but not consumed by the parser.
* This is usually
* done after reading all content of interest using parser.
* Content is released by writing it to given writer if possible;
* if underlying input is char-based it can released, if not (byte-based)
* it can not.
*
* @return -1 if the underlying content source is not char-based
* (that is, input can not be sent to {@link Writer};
* otherwise number of chars released (0 if there was nothing to release)
*
* @throws IOException if write using Writer threw exception
*/
public int releaseBuffered(Writer w) throws IOException { return -1; }
/*
/***************************************************
/* Public API, configuration
/***************************************************
*/
/*
/**********************************************************
/* Public API, traversal
/**********************************************************
*/
/*
* Main iteration method, which will advance stream enough
* to determine type of the next token, if any. If none
* remaining (stream has no content other than possible
* white space before ending), null will be returned.
*
* @return Next token from the stream, if any found, or null
* to indicate end-of-input
*/
public abstract JsonToken nextToken() throws IOException, JsonParseException;
/*
* Iteration method that will advance stream enough
* to determine type of the next token that is a value type
* (including JSON Array and Object start/end markers).
* Or put another way, nextToken() will be called once,
* and if {@link JsonToken#FIELD_NAME} is returned, another
* time to get the value for the field.
* Method is most useful for iterating over value entries
* of JSON objects; field name will still be available
* by calling {@link #getCurrentName} when parser points to
* the value.
*
* @return Next non-field-name token from the stream, if any found,
* or null to indicate end-of-input (or, for non-blocking
* parsers, {@link JsonToken#NOT_AVAILABLE} if no tokens were
* available yet)
*/
public abstract JsonToken nextValue() throws IOException, JsonParseException;
/*
* Method that fetches next token (as if calling {@link #nextToken}) and
* verifies whether it is {@link JsonToken#FIELD_NAME} with specified name
* and returns result of that comparison.
* It is functionally equivalent to:
*<pre>
* return (nextToken() == JsonToken.FIELD_NAME) && str.getValue().equals(getCurrentName());
*</pre>
* but may be faster for parser to verify, and can therefore be used if caller
* expects to get such a property name from input next.
*
* @param str Property name to compare next token to (if next token is <code>JsonToken.FIELD_NAME<code>)
*/
public boolean nextFieldName(SerializableString str) throws IOException, JsonParseException {
return (nextToken() == JsonToken.FIELD_NAME) && str.getValue().equals(getCurrentName());
}
/*
* Method that fetches next token (as if calling {@link #nextToken}) and
* if it is {@link JsonToken#VALUE_STRING} returns contained String value;
* otherwise returns null.
* It is functionally equivalent to:
*<pre>
* return (nextToken() == JsonToken.VALUE_STRING) ? getText() : null;
*</pre>
* but may be faster for parser to process, and can therefore be used if caller
* expects to get a String value next from input.
*/
public String nextTextValue() throws IOException, JsonParseException {
return (nextToken() == JsonToken.VALUE_STRING) ? getText() : null;
}
/*
* Method that fetches next token (as if calling {@link #nextToken}) and
* if it is {@link JsonToken#VALUE_NUMBER_INT} returns 32-bit int value;
* otherwise returns specified default value
* It is functionally equivalent to:
*<pre>
* return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getIntValue() : defaultValue;
*</pre>
* but may be faster for parser to process, and can therefore be used if caller
* expects to get a String value next from input.
*/
public int nextIntValue(int defaultValue) throws IOException, JsonParseException {
return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getIntValue() : defaultValue;
}
/*
* Method that fetches next token (as if calling {@link #nextToken}) and
* if it is {@link JsonToken#VALUE_NUMBER_INT} returns 64-bit long value;
* otherwise returns specified default value
* It is functionally equivalent to:
*<pre>
* return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getLongValue() : defaultValue;
*</pre>
* but may be faster for parser to process, and can therefore be used if caller
* expects to get a String value next from input.
*/
public long nextLongValue(long defaultValue) throws IOException, JsonParseException {
return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getLongValue() : defaultValue;
}
/*
* Method that fetches next token (as if calling {@link #nextToken}) and
* if it is {@link JsonToken#VALUE_TRUE} or {@link JsonToken#VALUE_FALSE}
* returns matching Boolean value; otherwise return null.
* It is functionally equivalent to:
*<pre>
* JsonToken t = nextToken();
* if (t == JsonToken.VALUE_TRUE) return Boolean.TRUE;
* if (t == JsonToken.VALUE_FALSE) return Boolean.FALSE;
* return null;
*</pre>
* but may be faster for parser to process, and can therefore be used if caller
* expects to get a String value next from input.
*/
public Boolean nextBooleanValue() throws IOException, JsonParseException {
JsonToken t = nextToken();
if (t == JsonToken.VALUE_TRUE) { return Boolean.TRUE; }
if (t == JsonToken.VALUE_FALSE) { return Boolean.FALSE; }
return null;
}
/*
* Method that will skip all child tokens of an array or
* object token that the parser currently points to,
* iff stream points to
* {@link JsonToken#START_OBJECT} or {@link JsonToken#START_ARRAY}.
* If not, it will do nothing.
* After skipping, stream will point to <b>matching</b>
* {@link JsonToken#END_OBJECT} or {@link JsonToken#END_ARRAY}
* (possibly skipping nested pairs of START/END OBJECT/ARRAY tokens
* as well as value tokens).
* The idea is that after calling this method, application
* will call {@link #nextToken} to point to the next
* available token, if any.
*/
public abstract JsonParser skipChildren() throws IOException, JsonParseException;
/*
* Method that can be called to determine whether this parser
* is closed or not. If it is closed, no new tokens can be
* retrieved by calling {@link #nextToken} (and the underlying
* stream may be closed). Closing may be due to an explicit
* call to {@link #close} or because parser has encountered
* end of input.
*/
public abstract boolean isClosed();
/*
/**********************************************************
/* Public API, token accessors
/**********************************************************
*/
/*
* Accessor to find which token parser currently points to, if any;
* null will be returned if none.
* If return value is non-null, data associated with the token
* is available via other accessor methods.
*
* @return Type of the token this parser currently points to,
* if any: null before any tokens have been read, and
* after end-of-input has been encountered, as well as
* if the current token has been explicitly cleared.
*/
public abstract JsonToken getCurrentToken();
/*
* Method similar to {@link #getCurrentToken()} but that returns an
* <code>int</code> instead of {@link JsonToken} (enum value).
*<p>
* Use of int directly is typically more efficient on switch statements,
* so this method may be useful when building low-overhead codecs.
* Note, however, that effect may not be big enough to matter: make sure
* to profile performance before deciding to use this method.
*
* @since 2.3
*
* @return <code>int</code> matching one of constants from {@link JsonTokenId}.
*/
public abstract int getCurrentTokenId();
/*
* Method for checking whether parser currently points to
* a token (and data for that token is available).
* Equivalent to check for <code>parser.getCurrentToken() != null</code>.
*
* @return True if the parser just returned a valid
* token via {@link #nextToken}; false otherwise (parser
* was just constructed, encountered end-of-input
* and returned null from {@link #nextToken}, or the token
* has been consumed)
*/
public abstract boolean hasCurrentToken();
/*
* Method that can be called to get the name associated with
* the current token: for {@link JsonToken#FIELD_NAME}s it will
* be the same as what {@link #getText} returns;
* for field values it will be preceding field name;
* and for others (array values, root-level values) null.
*/
public abstract String getCurrentName() throws IOException;
/*
* Method that can be used to access current parsing context reader
* is in. There are 3 different types: root, array and object contexts,
* with slightly different available information. Contexts are
* hierarchically nested, and can be used for example for figuring
* out part of the input document that correspond to specific
* array or object (for highlighting purposes, or error reporting).
* Contexts can also be used for simple xpath-like matching of
* input, if so desired.
*/
public abstract JsonStreamContext getParsingContext();
/*
* Method that return the <b>starting</b> location of the current
* token; that is, position of the first character from input
* that starts the current token.
*/
public abstract JsonLocation getTokenLocation();
/*
* Method that returns location of the last processed character;
* usually for error reporting purposes.
*/
public abstract JsonLocation getCurrentLocation();
/*
* Specialized accessor that can be used to verify that the current
* token indicates start array (usually meaning that current token
* is {@link JsonToken#START_ARRAY}) when start array is expected.
* For some specialized parsers this can return true for other cases
* as well; this is usually done to emulate arrays.
*<p>
* Default implementation is equivalent to:
*<pre>
* getCurrentToken() == JsonToken.START_ARRAY
*</pre>
* but may be overridden by custom parser implementations.
*
* @return True if the current token can be considered as a
* start-array marker (such {@link JsonToken#START_ARRAY});
* false if not.
*/
public boolean isExpectedStartArrayToken() { return getCurrentToken() == JsonToken.START_ARRAY; }
/*
/**********************************************************
/* Public API, token state overrides
/**********************************************************
*/
/*
* Method called to "consume" the current token by effectively
* removing it so that {@link #hasCurrentToken} returns false, and
* {@link #getCurrentToken} null).
* Cleared token value can still be accessed by calling
* {@link #getLastClearedToken} (if absolutely needed), but
* usually isn't.
*<p>
* Method was added to be used by the optional data binder, since
* it has to be able to consume last token used for binding (so that
* it will not be used again).
*/
public abstract void clearCurrentToken();
/*
* Method that can be called to get the last token that was
* cleared using {@link #clearCurrentToken}. This is not necessarily
* the latest token read.
* Will return null if no tokens have been cleared,
* or if parser has been closed.
*/
public abstract JsonToken getLastClearedToken();
/*
* Method that can be used to change what is considered to be
* the current (field) name.
* May be needed to support non-JSON data formats or unusual binding
* conventions; not needed for typical processing.
*<p>
* Note that use of this method should only be done as sort of last
* resort, as it is a work-around for regular operation.
*
* @param name Name to use as the current name; may be null.
*/
public abstract void overrideCurrentName(String name);
/*
/**********************************************************
/* Public API, access to token information, text
/**********************************************************
*/
/*
* Method for accessing textual representation of the current token;
* if no current token (before first call to {@link #nextToken}, or
* after encountering end-of-input), returns null.
* Method can be called for any token type.
*/
public abstract String getText() throws IOException;
/*
* Method similar to {@link #getText}, but that will return
* underlying (unmodifiable) character array that contains
* textual value, instead of constructing a String object
* to contain this information.
* Note, however, that:
*<ul>
* <li>Textual contents are not guaranteed to start at
* index 0 (rather, call {@link #getTextOffset}) to
* know the actual offset
* </li>
* <li>Length of textual contents may be less than the
* length of returned buffer: call {@link #getTextLength}
* for actual length of returned content.
* </li>
* </ul>
*<p>
* Note that caller <b>MUST NOT</b> modify the returned
* character array in any way -- doing so may corrupt
* current parser state and render parser instance useless.
*<p>
* The only reason to call this method (over {@link #getText})
* is to avoid construction of a String object (which
* will make a copy of contents).
*/
public abstract char[] getTextCharacters() throws IOException;
/*
* Accessor used with {@link #getTextCharacters}, to know length
* of String stored in returned buffer.
*
* @return Number of characters within buffer returned
* by {@link #getTextCharacters} that are part of
* textual content of the current token.
*/
public abstract int getTextLength() throws IOException;
/*
* Accessor used with {@link #getTextCharacters}, to know offset
* of the first text content character within buffer.
*
* @return Offset of the first character within buffer returned
* by {@link #getTextCharacters} that is part of
* textual content of the current token.
*/
public abstract int getTextOffset() throws IOException;
/*
* Method that can be used to determine whether calling of
* {@link #getTextCharacters} would be the most efficient
* way to access textual content for the event parser currently
* points to.
*<p>
* Default implementation simply returns false since only actual
* implementation class has knowledge of its internal buffering
* state.
* Implementations are strongly encouraged to properly override
* this method, to allow efficient copying of content by other
* code.
*
* @return True if parser currently has character array that can
* be efficiently returned via {@link #getTextCharacters}; false
* means that it may or may not exist
*/
public abstract boolean hasTextCharacters();
/*
/**********************************************************
/* Public API, access to token information, numeric
/**********************************************************
*/
/*
* Generic number value accessor method that will work for
* all kinds of numeric values. It will return the optimal
* (simplest/smallest possible) wrapper object that can
* express the numeric value just parsed.
*/
public abstract Number getNumberValue() throws IOException;
/*
* If current token is of type
* {@link JsonToken#VALUE_NUMBER_INT} or
* {@link JsonToken#VALUE_NUMBER_FLOAT}, returns
* one of {@link NumberType} constants; otherwise returns null.
*/
public abstract NumberType getNumberType() throws IOException;
/*
* Numeric accessor that can be called when the current
* token is of type {@link JsonToken#VALUE_NUMBER_INT} and
* it can be expressed as a value of Java byte primitive type.
* It can also be called for {@link JsonToken#VALUE_NUMBER_FLOAT};
* if so, it is equivalent to calling {@link #getDoubleValue}
* and then casting; except for possible overflow/underflow
* exception.
*<p>
* Note: if the resulting integer value falls outside range of
* Java byte, a {@link JsonParseException}
* will be thrown to indicate numeric overflow/underflow.
*/
public byte getByteValue() throws IOException {
int value = getIntValue();
// So far so good: but does it fit?
// [JACKSON-804]: Let's actually allow range of [-128, 255], as those are uniquely mapped
// (instead of just signed range of [-128, 127])
if (value < MIN_BYTE_I || value > MAX_BYTE_I) {
throw _constructError("Numeric value ("+getText()+") out of range of Java byte");
}
return (byte) value;
}
/*
* Numeric accessor that can be called when the current
* token is of type {@link JsonToken#VALUE_NUMBER_INT} and
* it can be expressed as a value of Java short primitive type.
* It can also be called for {@link JsonToken#VALUE_NUMBER_FLOAT};
* if so, it is equivalent to calling {@link #getDoubleValue}
* and then casting; except for possible overflow/underflow
* exception.
*<p>
* Note: if the resulting integer value falls outside range of
* Java short, a {@link JsonParseException}
* will be thrown to indicate numeric overflow/underflow.
*/
public short getShortValue() throws IOException
{
int value = getIntValue();
if (value < MIN_SHORT_I || value > MAX_SHORT_I) {
throw _constructError("Numeric value ("+getText()+") out of range of Java short");
}
return (short) value;
}
/*
* Numeric accessor that can be called when the current
* token is of type {@link JsonToken#VALUE_NUMBER_INT} and
* it can be expressed as a value of Java int primitive type.
* It can also be called for {@link JsonToken#VALUE_NUMBER_FLOAT};
* if so, it is equivalent to calling {@link #getDoubleValue}
* and then casting; except for possible overflow/underflow
* exception.
*<p>
* Note: if the resulting integer value falls outside range of
* Java int, a {@link JsonParseException}
* may be thrown to indicate numeric overflow/underflow.
*/
public abstract int getIntValue() throws IOException;
/*
* Numeric accessor that can be called when the current
* token is of type {@link JsonToken#VALUE_NUMBER_INT} and
* it can be expressed as a Java long primitive type.
* It can also be called for {@link JsonToken#VALUE_NUMBER_FLOAT};
* if so, it is equivalent to calling {@link #getDoubleValue}
* and then casting to int; except for possible overflow/underflow
* exception.
*<p>
* Note: if the token is an integer, but its value falls
* outside of range of Java long, a {@link JsonParseException}
* may be thrown to indicate numeric overflow/underflow.
*/
public abstract long getLongValue() throws IOException;
/*
* Numeric accessor that can be called when the current
* token is of type {@link JsonToken#VALUE_NUMBER_INT} and
* it can not be used as a Java long primitive type due to its
* magnitude.
* It can also be called for {@link JsonToken#VALUE_NUMBER_FLOAT};
* if so, it is equivalent to calling {@link #getDecimalValue}
* and then constructing a {@link BigInteger} from that value.
*/
public abstract BigInteger getBigIntegerValue() throws IOException;
/*
* Numeric accessor that can be called when the current
* token is of type {@link JsonToken#VALUE_NUMBER_FLOAT} and
* it can be expressed as a Java float primitive type.
* It can also be called for {@link JsonToken#VALUE_NUMBER_INT};
* if so, it is equivalent to calling {@link #getLongValue}
* and then casting; except for possible overflow/underflow
* exception.
*<p>
* Note: if the value falls
* outside of range of Java float, a {@link JsonParseException}
* will be thrown to indicate numeric overflow/underflow.
*/
public abstract float getFloatValue() throws IOException;
/*
* Numeric accessor that can be called when the current
* token is of type {@link JsonToken#VALUE_NUMBER_FLOAT} and
* it can be expressed as a Java double primitive type.
* It can also be called for {@link JsonToken#VALUE_NUMBER_INT};
* if so, it is equivalent to calling {@link #getLongValue}
* and then casting; except for possible overflow/underflow
* exception.
*<p>
* Note: if the value falls
* outside of range of Java double, a {@link JsonParseException}
* will be thrown to indicate numeric overflow/underflow.
*/
public abstract double getDoubleValue() throws IOException;
/*
* Numeric accessor that can be called when the current
* token is of type {@link JsonToken#VALUE_NUMBER_FLOAT} or
* {@link JsonToken#VALUE_NUMBER_INT}. No under/overflow exceptions
* are ever thrown.
*/
public abstract BigDecimal getDecimalValue() throws IOException;
/*
/**********************************************************
/* Public API, access to token information, other
/**********************************************************
*/
/*
* Convenience accessor that can be called when the current
* token is {@link JsonToken#VALUE_TRUE} or
* {@link JsonToken#VALUE_FALSE}.
*<p>
* Note: if the token is not of above-mentioned boolean types,
an integer, but its value falls
* outside of range of Java long, a {@link JsonParseException}
* may be thrown to indicate numeric overflow/underflow.
*/
public boolean getBooleanValue() throws IOException {
JsonToken t = getCurrentToken();
if (t == JsonToken.VALUE_TRUE) return true;
if (t == JsonToken.VALUE_FALSE) return false;
throw new JsonParseException("Current token ("+t+") not of boolean type", getCurrentLocation());
}
/*
* Accessor that can be called if (and only if) the current token
* is {@link JsonToken#VALUE_EMBEDDED_OBJECT}. For other token types,
* null is returned.
*<p>
* Note: only some specialized parser implementations support
* embedding of objects (usually ones that are facades on top
* of non-streaming sources, such as object trees).
*/
public abstract Object getEmbeddedObject() throws IOException;
/*
/**********************************************************
/* Public API, access to token information, binary
/**********************************************************
*/
/*
* Method that can be used to read (and consume -- results
* may not be accessible using other methods after the call)
* base64-encoded binary data
* included in the current textual JSON value.
* It works similar to getting String value via {@link #getText}
* and decoding result (except for decoding part),
* but should be significantly more performant.
*<p>
* Note that non-decoded textual contents of the current token
* are not guaranteed to be accessible after this method
* is called. Current implementation, for example, clears up
* textual content during decoding.
* Decoded binary content, however, will be retained until
* parser is advanced to the next event.
*
* @param bv Expected variant of base64 encoded
* content (see {@link Base64Variants} for definitions
* of "standard" variants).
*
* @return Decoded binary data
*/
public abstract byte[] getBinaryValue(Base64Variant bv) throws IOException;
/*
* Convenience alternative to {@link #getBinaryValue(Base64Variant)}
* that defaults to using
* {@link Base64Variants#getDefaultVariant} as the default encoding.
*/
public byte[] getBinaryValue() throws IOException {
return getBinaryValue(Base64Variants.getDefaultVariant());
}
/*
* Method that can be used as an alternative to {@link #getBigIntegerValue()},
* especially when value can be large. The main difference (beyond method
* of returning content using {@link OutputStream} instead of as byte array)
* is that content will NOT remain accessible after method returns: any content
* processed will be consumed and is not buffered in any way. If caller needs
* buffering, it has to implement it.
*
* @param out Output stream to use for passing decoded binary data
*
* @return Number of bytes that were decoded and written via {@link OutputStream}
*
* @since 2.1
*/
public int readBinaryValue(OutputStream out) throws IOException {
return readBinaryValue(Base64Variants.getDefaultVariant(), out);
}
/*
* Similar to {@link #readBinaryValue(OutputStream)} but allows explicitly
* specifying base64 variant to use.
*
* @param bv base64 variant to use
* @param out Output stream to use for passing decoded binary data
*
* @return Number of bytes that were decoded and written via {@link OutputStream}
*
* @since 2.1
*/
public int readBinaryValue(Base64Variant bv, OutputStream out) throws IOException {
_reportUnsupportedOperation();
return 0; // never gets here
}
/*
/**********************************************************
/* Public API, access to token information, coercion/conversion
/**********************************************************
*/
/*
* Method that will try to convert value of current token to a
* <b>int</b>.
* Numbers are coerced using default Java rules; booleans convert to 0 (false)
* and 1 (true), and Strings are parsed using default Java language integer
* parsing rules.
*<p>
* If representation can not be converted to an int (including structured type
* markers like start/end Object/Array)
* default value of <b>0</b> will be returned; no exceptions are thrown.
*/
public int getValueAsInt() throws IOException {
return getValueAsInt(0);
}
/*
* Method that will try to convert value of current token to a
* <b>int</b>.
* Numbers are coerced using default Java rules; booleans convert to 0 (false)
* and 1 (true), and Strings are parsed using default Java language integer
* parsing rules.
*<p>
* If representation can not be converted to an int (including structured type
* markers like start/end Object/Array)
* specified <b>def</b> will be returned; no exceptions are thrown.
*/
public int getValueAsInt(int def) throws IOException { return def; }
/*
* Method that will try to convert value of current token to a
* <b>long</b>.
* Numbers are coerced using default Java rules; booleans convert to 0 (false)
* and 1 (true), and Strings are parsed using default Java language integer
* parsing rules.
*<p>
* If representation can not be converted to an int (including structured type
* markers like start/end Object/Array)
* default value of <b>0</b> will be returned; no exceptions are thrown.
*/
public long getValueAsLong() throws IOException {
return getValueAsLong(0);
}
/*
* Method that will try to convert value of current token to a
* <b>long</b>.
* Numbers are coerced using default Java rules; booleans convert to 0 (false)
* and 1 (true), and Strings are parsed using default Java language integer
* parsing rules.
*<p>
* If representation can not be converted to an int (including structured type
* markers like start/end Object/Array)
* specified <b>def</b> will be returned; no exceptions are thrown.
*/
public long getValueAsLong(long def) throws IOException {
return def;
}
/*
* Method that will try to convert value of current token to a Java
* <b>double</b>.
* Numbers are coerced using default Java rules; booleans convert to 0.0 (false)
* and 1.0 (true), and Strings are parsed using default Java language integer
* parsing rules.
*<p>
* If representation can not be converted to an int (including structured types
* like Objects and Arrays),
* default value of <b>0.0</b> will be returned; no exceptions are thrown.
*/
public double getValueAsDouble() throws IOException {
return getValueAsDouble(0.0);
}
/*
* Method that will try to convert value of current token to a
* Java <b>double</b>.
* Numbers are coerced using default Java rules; booleans convert to 0.0 (false)
* and 1.0 (true), and Strings are parsed using default Java language integer
* parsing rules.
*<p>
* If representation can not be converted to an int (including structured types
* like Objects and Arrays),
* specified <b>def</b> will be returned; no exceptions are thrown.
*/
public double getValueAsDouble(double def) throws IOException {
return def;
}
/*
* Method that will try to convert value of current token to a
* <b>boolean</b>.
* JSON booleans map naturally; integer numbers other than 0 map to true, and
* 0 maps to false
* and Strings 'true' and 'false' map to corresponding values.
*<p>
* If representation can not be converted to a boolean value (including structured types
* like Objects and Arrays),
* default value of <b>false</b> will be returned; no exceptions are thrown.
*/
public boolean getValueAsBoolean() throws IOException {
return getValueAsBoolean(false);
}
/*
* Method that will try to convert value of current token to a
* <b>boolean</b>.
* JSON booleans map naturally; integer numbers other than 0 map to true, and
* 0 maps to false
* and Strings 'true' and 'false' map to corresponding values.
*<p>
* If representation can not be converted to a boolean value (including structured types
* like Objects and Arrays),
* specified <b>def</b> will be returned; no exceptions are thrown.
*/
public boolean getValueAsBoolean(boolean def) throws IOException {
return def;
}
/*
* Method that will try to convert value of current token to a
* {@link java.lang.String}.
* JSON Strings map naturally; scalar values get converted to
* their textual representation.
* If representation can not be converted to a String value (including structured types
* like Objects and Arrays and null token), default value of
* <b>null</b> will be returned; no exceptions are thrown.
*
* @since 2.1
*/
public String getValueAsString() throws IOException {
return getValueAsString(null);
}
/*
* Method that will try to convert value of current token to a
* {@link java.lang.String}.
* JSON Strings map naturally; scalar values get converted to
* their textual representation.
* If representation can not be converted to a String value (including structured types
* like Objects and Arrays and null token), specified default value
* will be returned; no exceptions are thrown.
*
* @since 2.1
*/
public abstract String getValueAsString(String def) throws IOException;
/*
/**********************************************************
/* Public API, Native Ids (type, object)
/**********************************************************
*/
/*
* Introspection method that may be called to see if the underlying
* data format supports some kind of Object Ids natively (many do not;
* for example, JSON doesn't).
*<p>
* Default implementation returns true; overridden by data formats
* that do support native Object Ids. Caller is expected to either
* use a non-native notation (explicit property or such), or fail,
* in case it can not use native object ids.
*
* @since 2.3
*/
public boolean canReadObjectId() { return false; }
/*
* Introspection method that may be called to see if the underlying
* data format supports some kind of Type Ids natively (many do not;
* for example, JSON doesn't).
*<p>
* Default implementation returns true; overridden by data formats
* that do support native Type Ids. Caller is expected to either
* use a non-native notation (explicit property or such), or fail,
* in case it can not use native type ids.
*
* @since 2.3
*/
public boolean canReadTypeId() { return false; }
/*
* Method that can be called to check whether current token
* (one that was just read) has an associated Object id, and if
* so, return it.
* Note that while typically caller should check with {@link #canReadObjectId}
* first, it is not illegal to call this method even if that method returns
* true; but if so, it will return null. This may be used to simplify calling
* code.
*<p>
* Default implementation will simply return null.
*
* @since 2.3
*/
public Object getObjectId() throws IOException { return null; }
/*
* Method that can be called to check whether current token
* (one that was just read) has an associated type id, and if
* so, return it.
* Note that while typically caller should check with {@link #canReadTypeId}
* first, it is not illegal to call this method even if that method returns
* true; but if so, it will return null. This may be used to simplify calling
* code.
*<p>
* Default implementation will simply return null.
*
* @since 2.3
*/
public Object getTypeId() throws IOException { return null; }
/*
/**********************************************************
/* Internal methods
/**********************************************************
*/
/*
* Helper method for constructing {@link JsonParseException}s
* based on current state of the parser
*/
protected JsonParseException _constructError(String msg) {
return new JsonParseException(msg, getCurrentLocation());
}
/*
* Helper method to call for operations that are not supported by
* parser implementation.
*
* @since 2.1
*/
protected void _reportUnsupportedOperation() {
throw new UnsupportedOperationException("Operation not supported by parser of type "+getClass().getName());
}
}