org.codehaus.jackson.map.ObjectReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ehcache Show documentation
Show all versions of ehcache Show documentation
Ehcache is an open source, standards-based cache used to boost performance,
offload the database and simplify scalability. Ehcache is robust, proven and full-featured and
this has made it the most widely-used Java-based cache.
package org.codehaus.jackson.map;
import java.io.*;
import java.net.URL;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import org.codehaus.jackson.*;
import org.codehaus.jackson.io.SerializedString;
import org.codehaus.jackson.map.deser.StdDeserializationContext;
import org.codehaus.jackson.map.type.SimpleType;
import org.codehaus.jackson.node.JsonNodeFactory;
import org.codehaus.jackson.node.NullNode;
import org.codehaus.jackson.node.TreeTraversingParser;
import org.codehaus.jackson.type.JavaType;
import org.codehaus.jackson.type.TypeReference;
import org.codehaus.jackson.util.VersionUtil;
/**
* Builder object that can be used for per-serialization configuration of
* deserialization parameters, such as root type to use or object
* to update (instead of constructing new instance).
* Uses "fluid" (aka builder) pattern so that instances are immutable
* (and thus fully thread-safe with no external synchronization);
* new instances are constructed for different configurations.
* Instances are initially constructed by {@link ObjectMapper} and can be
* reused.
*
* @author tatu
* @since 1.6
*/
public class ObjectReader
extends ObjectCodec
implements Versioned
{
private final static JavaType JSON_NODE_TYPE = SimpleType.constructUnsafe(JsonNode.class);
/*
/**********************************************************
/* Immutable configuration from ObjectMapper
/**********************************************************
*/
/**
* General serialization configuration settings; while immutable,
* can use copy-constructor to create modified instances as necessary.
*/
protected final DeserializationConfig _config;
/**
* Flag that indicates whether root values are expected to be unwrapped
* or not
*
* @since 1.9
*/
protected final boolean _unwrapRoot;
/**
* Root-level cached deserializers
*/
final protected ConcurrentHashMap> _rootDeserializers;
protected final DeserializerProvider _provider;
/**
* Factory used for constructing {@link JsonGenerator}s
*/
protected final JsonFactory _jsonFactory;
/*
/**********************************************************
/* Configuration that can be changed during building
/**********************************************************
*/
/**
* Declared type of value to instantiate during deserialization.
* Defines which deserializer to use; as well as base type of instance
* to construct if an updatable value is not configured to be used
* (subject to changes by embedded type information, for polymorphic
* types). If {@link #_valueToUpdate} is non-null, only used for
* locating deserializer.
*/
protected final JavaType _valueType;
/**
* Instance to update with data binding; if any. If null,
* a new instance is created, if non-null, properties of
* this value object will be updated instead.
* Note that value can be of almost any type, except not
* {@link org.codehaus.jackson.map.type.ArrayType}; array
* types can not be modified because array size is immutable.
*/
protected final Object _valueToUpdate;
/**
* When using data format that uses a schema, schema is passed
* to parser.
*
* @since 1.8
*/
protected final FormatSchema _schema;
/**
* Values that can be injected during deserialization, if any.
*
* @since 1.9
*/
protected final InjectableValues _injectableValues;
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
/**
* Constructor used by {@link ObjectMapper} for initial instantiation
*
* @since 1.8
*/
protected ObjectReader(ObjectMapper mapper, DeserializationConfig config)
{
this(mapper, config, null, null, null, null);
}
protected ObjectReader(ObjectMapper mapper, DeserializationConfig config,
JavaType valueType, Object valueToUpdate, FormatSchema schema,
InjectableValues injectableValues)
{
_config = config;
_rootDeserializers = mapper._rootDeserializers;
_provider = mapper._deserializerProvider;
_jsonFactory = mapper._jsonFactory;
_valueType = valueType;
_valueToUpdate = valueToUpdate;
if (valueToUpdate != null && valueType.isArrayType()) {
throw new IllegalArgumentException("Can not update an array value");
}
_schema = schema;
_injectableValues = injectableValues;
_unwrapRoot = config.isEnabled(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE);
}
/**
* Copy constructor used for building variations.
*/
protected ObjectReader(ObjectReader base, DeserializationConfig config,
JavaType valueType, Object valueToUpdate, FormatSchema schema,
InjectableValues injectableValues)
{
_config = config;
_rootDeserializers = base._rootDeserializers;
_provider = base._provider;
_jsonFactory = base._jsonFactory;
_valueType = valueType;
_valueToUpdate = valueToUpdate;
if (valueToUpdate != null && valueType.isArrayType()) {
throw new IllegalArgumentException("Can not update an array value");
}
_schema = schema;
_injectableValues = injectableValues;
_unwrapRoot = config.isEnabled(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE);
}
/**
* Method that will return version information stored in and read from jar
* that contains this class.
*
* @since 1.6
*/
@Override
public Version version() {
return VersionUtil.versionFor(getClass());
}
public ObjectReader withType(JavaType valueType)
{
if (valueType == _valueType) return this;
// type is stored here, no need to make a copy of config
return new ObjectReader(this, _config, valueType, _valueToUpdate,
_schema, _injectableValues);
}
public ObjectReader withType(Class> valueType)
{
return withType(_config.constructType(valueType));
}
public ObjectReader withType(java.lang.reflect.Type valueType)
{
return withType(_config.getTypeFactory().constructType(valueType));
}
/**
* @since 1.8
*/
public ObjectReader withType(TypeReference> valueTypeRef)
{
return withType(_config.getTypeFactory().constructType(valueTypeRef.getType()));
}
public ObjectReader withNodeFactory(JsonNodeFactory f)
{
// node factory is stored within config, so need to copy that first
if (f == _config.getNodeFactory()) return this;
return new ObjectReader(this, _config.withNodeFactory(f), _valueType, _valueToUpdate,
_schema, _injectableValues);
}
public ObjectReader withValueToUpdate(Object value)
{
if (value == _valueToUpdate) return this;
if (value == null) {
throw new IllegalArgumentException("cat not update null value");
}
JavaType t = _config.constructType(value.getClass());
return new ObjectReader(this, _config, t, value,
_schema, _injectableValues);
}
/**
* @since 1.8
*/
public ObjectReader withSchema(FormatSchema schema)
{
if (_schema == schema) {
return this;
}
return new ObjectReader(this, _config, _valueType, _valueToUpdate,
schema, _injectableValues);
}
/**
* @since 1.9
*/
public ObjectReader withInjectableValues(InjectableValues injectableValues)
{
if (_injectableValues == injectableValues) {
return this;
}
return new ObjectReader(this, _config, _valueType, _valueToUpdate,
_schema, injectableValues);
}
/*
/**********************************************************
/* Deserialization methods; basic ones to support ObjectCodec first
/* (ones that take JsonParser)
/**********************************************************
*/
// not part of ObjectCodec, actually
@SuppressWarnings("unchecked")
public T readValue(JsonParser jp)
throws IOException, JsonProcessingException
{
return (T) _bind(jp);
}
@SuppressWarnings("unchecked")
@Override
public T readValue(JsonParser jp, Class valueType)
throws IOException, JsonProcessingException
{
return (T) withType(valueType).readValue(jp);
}
@SuppressWarnings("unchecked")
@Override
public T readValue(JsonParser jp, TypeReference> valueTypeRef) throws IOException, JsonProcessingException
{
return (T) withType(valueTypeRef).readValue(jp);
}
@SuppressWarnings("unchecked")
@Override
public T readValue(JsonParser jp, JavaType valueType) throws IOException, JsonProcessingException {
return (T) withType(valueType).readValue(jp);
}
@Override
public JsonNode readTree(JsonParser jp)
throws IOException, JsonProcessingException
{
return _bindAsTree(jp);
}
@Override
public Iterator readValues(JsonParser jp, Class valueType)
throws IOException, JsonProcessingException {
return withType(valueType).readValues(jp);
}
@Override
public Iterator readValues(JsonParser jp, TypeReference> valueTypeRef)
throws IOException, JsonProcessingException {
return withType(valueTypeRef).readValues(jp);
}
@Override
public Iterator readValues(JsonParser jp, JavaType valueType)
throws IOException, JsonProcessingException {
return withType(valueType).readValues(jp);
}
/*
/**********************************************************
/* Deserialization methods; others similar to what ObjectMapper has
/**********************************************************
*/
@SuppressWarnings("unchecked")
public T readValue(InputStream src)
throws IOException, JsonProcessingException
{
return (T) _bindAndClose(_jsonFactory.createJsonParser(src));
}
@SuppressWarnings("unchecked")
public T readValue(Reader src)
throws IOException, JsonProcessingException
{
return (T) _bindAndClose(_jsonFactory.createJsonParser(src));
}
@SuppressWarnings("unchecked")
public T readValue(String src)
throws IOException, JsonProcessingException
{
return (T) _bindAndClose(_jsonFactory.createJsonParser(src));
}
@SuppressWarnings("unchecked")
public T readValue(byte[] src)
throws IOException, JsonProcessingException
{
return (T) _bindAndClose(_jsonFactory.createJsonParser(src));
}
@SuppressWarnings("unchecked")
public T readValue(byte[] src, int offset, int length)
throws IOException, JsonProcessingException
{
return (T) _bindAndClose(_jsonFactory.createJsonParser(src, offset, length));
}
@SuppressWarnings("unchecked")
public T readValue(File src)
throws IOException, JsonProcessingException
{
return (T) _bindAndClose(_jsonFactory.createJsonParser(src));
}
@SuppressWarnings("unchecked")
public T readValue(URL src)
throws IOException, JsonProcessingException
{
return (T) _bindAndClose(_jsonFactory.createJsonParser(src));
}
/**
* Convenience method for converting results from given JSON tree into given
* value type. Basically short-cut for:
*
* objectReader.readValue(src.traverse())
*
*/
@SuppressWarnings("unchecked")
public T readValue(JsonNode src)
throws IOException, JsonProcessingException
{
return (T) _bindAndClose(treeAsTokens(src));
}
public JsonNode readTree(InputStream in)
throws IOException, JsonProcessingException
{
return _bindAndCloseAsTree(_jsonFactory.createJsonParser(in));
}
public JsonNode readTree(Reader r)
throws IOException, JsonProcessingException
{
return _bindAndCloseAsTree(_jsonFactory.createJsonParser(r));
}
public JsonNode readTree(String content)
throws IOException, JsonProcessingException
{
return _bindAndCloseAsTree(_jsonFactory.createJsonParser(content));
}
/*
/**********************************************************
/* Deserialization methods; reading sequence of values
/**********************************************************
*/
/**
* Method for reading sequence of Objects from parser stream.
*
* @since 1.8
*/
public MappingIterator readValues(JsonParser jp)
throws IOException, JsonProcessingException
{
DeserializationContext ctxt = _createDeserializationContext(jp, _config);
return new MappingIterator(_valueType, jp, ctxt, _findRootDeserializer(_config, _valueType));
}
/**
* Method for reading sequence of Objects from parser stream.
*
* @since 1.8
*/
public MappingIterator readValues(InputStream src)
throws IOException, JsonProcessingException
{
JsonParser jp = _jsonFactory.createJsonParser(src);
if (_schema != null) {
jp.setSchema(_schema);
}
DeserializationContext ctxt = _createDeserializationContext(jp, _config);
return new MappingIterator(_valueType, jp, ctxt, _findRootDeserializer(_config, _valueType));
}
/**
* Method for reading sequence of Objects from parser stream.
*
* @since 1.8
*/
public MappingIterator readValues(Reader src)
throws IOException, JsonProcessingException
{
JsonParser jp = _jsonFactory.createJsonParser(src);
if (_schema != null) {
jp.setSchema(_schema);
}
DeserializationContext ctxt = _createDeserializationContext(jp, _config);
return new MappingIterator(_valueType, jp, ctxt, _findRootDeserializer(_config, _valueType));
}
/**
* Method for reading sequence of Objects from parser stream.
*
* @since 1.8
*/
public MappingIterator readValues(String json)
throws IOException, JsonProcessingException
{
JsonParser jp = _jsonFactory.createJsonParser(json);
if (_schema != null) {
jp.setSchema(_schema);
}
DeserializationContext ctxt = _createDeserializationContext(jp, _config);
return new MappingIterator(_valueType, jp, ctxt, _findRootDeserializer(_config, _valueType));
}
/**
* Method for reading sequence of Objects from parser stream.
*
* @since 1.8
*/
public MappingIterator readValues(byte[] src, int offset, int length)
throws IOException, JsonProcessingException
{
JsonParser jp = _jsonFactory.createJsonParser(src, offset, length);
if (_schema != null) {
jp.setSchema(_schema);
}
DeserializationContext ctxt = _createDeserializationContext(jp, _config);
return new MappingIterator(_valueType, jp, ctxt, _findRootDeserializer(_config, _valueType));
}
/**
* Method for reading sequence of Objects from parser stream.
*
* @since 1.8
*/
public MappingIterator readValues(File src)
throws IOException, JsonProcessingException
{
JsonParser jp = _jsonFactory.createJsonParser(src);
if (_schema != null) {
jp.setSchema(_schema);
}
DeserializationContext ctxt = _createDeserializationContext(jp, _config);
return new MappingIterator(_valueType, jp, ctxt, _findRootDeserializer(_config, _valueType));
}
/**
* Method for reading sequence of Objects from parser stream.
*
* @since 1.8
*/
public MappingIterator readValues(URL src)
throws IOException, JsonProcessingException
{
JsonParser jp = _jsonFactory.createJsonParser(src);
if (_schema != null) {
jp.setSchema(_schema);
}
DeserializationContext ctxt = _createDeserializationContext(jp, _config);
return new MappingIterator(_valueType, jp, ctxt, _findRootDeserializer(_config, _valueType));
}
/*
/**********************************************************
/* Helper methods
/**********************************************************
*/
/**
* Actual implementation of value reading+binding operation.
*/
protected Object _bind(JsonParser jp)
throws IOException, JsonParseException, JsonMappingException
{
/* First: may need to read the next token, to initialize state (either
* before first read from parser, or after previous token has been cleared)
*/
Object result;
JsonToken t = _initForReading(jp);
if (t == JsonToken.VALUE_NULL) {
if (_valueToUpdate == null) {
result = _findRootDeserializer(_config, _valueType).getNullValue();
} else {
result = _valueToUpdate;
}
} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {
result = _valueToUpdate;
} else { // pointing to event other than null
DeserializationContext ctxt = _createDeserializationContext(jp, _config);
JsonDeserializer