com.fasterxml.jackson.jr.ob.impl.JSONReader Maven / Gradle / Ivy
Show all versions of jackson-jr-all Show documentation
package com.fasterxml.jackson.jr.ob.impl;
import java.io.*;
import java.util.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.jr.ob.JSON;
import com.fasterxml.jackson.jr.ob.JSONObjectException;
import com.fasterxml.jackson.jr.ob.api.CollectionBuilder;
import com.fasterxml.jackson.jr.ob.api.MapBuilder;
import com.fasterxml.jackson.jr.ob.api.ValueReader;
/**
* Root-level helper object that handles initial delegation to actual
* readers (which are {@link ValueReader}s), but does not handle
* any of reading itself (despite name).
*
* Life-cycle is such that initial instance (called blueprint)
* is constructed first (including possible configuration
* using mutant factory methods). This blueprint object
* acts as a factory, and is never used for direct reading;
* instead, per-call instance is created by calling
* {@link #perOperationInstance}.
*/
public class JSONReader
{
/*
/**********************************************************************
/* Blueprint config
/**********************************************************************
*/
/**
* Handler that takes care of constructing {@link java.util.Map}s as needed
*/
protected final MapBuilder _mapBuilder;
/**
* Handler that takes care of constructing {@link java.util.Map}s as needed
*/
protected final CollectionBuilder _collectionBuilder;
/*
/**********************************************************************
/* Instance config, state
/**********************************************************************
*/
protected final int _features;
/**
* Configured {@link TreeCodec} that is needed if values of type {@link TreeNode}
* are to be read.
*/
protected final TreeCodec _treeCodec;
/**
* Object that is used to find value readers dynamically.
*/
protected final ValueReaderLocator _readerLocator;
/**
* Parser used by this reader instance.
*/
protected final JsonParser _parser;
/**
* Minor performance optimization: {@code Object[1]} reused to avoid
* Reflection having to allocate it for every "setter" call.
*
* @since 2.13
*/
protected final Object[] _setterBuffer;
/*
/**********************************************************************
/* Blueprint construction
/**********************************************************************
*/
/**
* Constructor used for creating the blueprint instances.
*/
public JSONReader(CollectionBuilder lb, MapBuilder mb)
{
_features = 0;
_readerLocator = null;
_treeCodec = null;
_collectionBuilder = lb;
_mapBuilder = mb;
_parser = null;
_setterBuffer = null; // should NOT be used on blueprint
}
/**
* Constructor used for per-operation (non-blueprint) instance.
*/
protected JSONReader(JSONReader base, int features,
ValueReaderLocator loc, TreeCodec tc, JsonParser p)
{
_features = features;
_readerLocator = loc.perOperationInstance(this, features);
_treeCodec = tc;
_collectionBuilder = base._collectionBuilder.newBuilder(features);
_mapBuilder = base._mapBuilder.newBuilder(features);
_parser = p;
_setterBuffer = new Object[1];
}
/*
/**********************************************************************
/* Mutant factories for blueprint
/**********************************************************************
*/
public JSONReader withCacheCheck(int features) {
// 07-Jun-2019, tatu: No cache-dependant clearing needed... yet.
return this;
}
public JSONReader with(MapBuilder mb) {
if (_mapBuilder == mb) return this;
return _with(_collectionBuilder, mb);
}
public JSONReader with(CollectionBuilder lb) {
if (_collectionBuilder == lb) return this;
return _with(lb, _mapBuilder);
}
/**
* Overridable method that all mutant factories call if a new instance
* is to be constructed
*/
protected JSONReader _with(CollectionBuilder lb, MapBuilder mb)
{
if (getClass() != JSONReader.class) { // sanity check
throw new IllegalStateException("Sub-classes MUST override _with(...)");
}
return new JSONReader(lb, mb);
}
/*
/**********************************************************************
/* New instance creation
/**********************************************************************
*/
public JSONReader perOperationInstance(int features,
ValueReaderLocator loc, TreeCodec tc,
JsonParser p)
{
if (getClass() != JSONReader.class) { // sanity check
throw new IllegalStateException("Sub-classes MUST override perOperationInstance(...)");
}
return new JSONReader(this, features, loc, tc, p);
}
/*
/**********************************************************************
/* Simple accessors
/**********************************************************************
*/
/**
* @since 2.8
*/
public boolean arraysAsLists() {
return JSON.Feature.READ_JSON_ARRAYS_AS_JAVA_ARRAYS.isDisabled(_features);
}
/**
* @since 2.11
*/
public boolean isEnabled(JSON.Feature f) {
return f.isEnabled(_features);
}
/**
* @since 2.13
*/
public int features() {
return _features;
}
/*
/**********************************************************************
/* Public entry points for reading Simple objects from JSON
/**********************************************************************
*/
/**
* Method for reading a "simple" Object of type indicated by JSON
* content: {@link java.util.Map} for JSON Object, {@link java.util.Map}
* for JSON Array (or, Object[]
if so configured),
* {@link java.lang.String} for JSON String value and so on.
*/
public Object readValue() throws IOException {
return AnyReader.std.read(this, _parser);
}
/**
* Method for reading a JSON Object from input and building a {@link java.util.Map}
* out of it. Note that if input does NOT contain a
* JSON Object, {@link JSONObjectException} will be thrown.
*/
public Map readMap() throws IOException {
JsonToken t = _parser.currentToken();
if (t == JsonToken.VALUE_NULL) {
return null;
}
if (t != JsonToken.START_OBJECT) {
throw JSONObjectException.from(_parser,
"Can not read a Map: expect to see START_OBJECT ('{'), instead got: "+ValueReader._tokenDesc(_parser));
}
return AnyReader.std.readFromObject(this, _parser, _mapBuilder);
}
/**
* Method for reading a JSON Array from input and building a {@link java.util.List}
* out of it. Note that if input does NOT contain a
* JSON Array, {@link JSONObjectException} will be thrown.
*/
public List