Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.fasterxml.jackson.databind.deser.std.StringCollectionDeserializer Maven / Gradle / Ivy
package com.fasterxml.jackson.databind.deser.std;
import java.io.IOException;
import java.util.Collection;
import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.cfg.CoercionAction;
import com.fasterxml.jackson.databind.cfg.CoercionInputShape;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.deser.NullValueProvider;
import com.fasterxml.jackson.databind.deser.ValueInstantiator;
import com.fasterxml.jackson.databind.introspect.AnnotatedWithParams;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fasterxml.jackson.databind.type.LogicalType;
/**
* Specifically optimized version for {@link java.util.Collection}s
* that contain String values; reason is that this is a very common
* type and we can make use of the fact that Strings are final.
*/
@JacksonStdImpl
public final class StringCollectionDeserializer
extends ContainerDeserializerBase>
implements ContextualDeserializer
{
private static final long serialVersionUID = 1L;
// // Configuration
/**
* Value deserializer to use, if NOT the standard one
* (if it is, will be null).
*/
protected final JsonDeserializer _valueDeserializer;
// // Instance construction settings:
/**
* Instantiator used in case custom handling is needed for creation.
*/
protected final ValueInstantiator _valueInstantiator;
/**
* Deserializer that is used iff delegate-based creator is
* to be used for deserializing from JSON Object.
*/
protected final JsonDeserializer _delegateDeserializer;
// NOTE: no PropertyBasedCreator, as JSON Arrays have no properties
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
public StringCollectionDeserializer(JavaType collectionType,
JsonDeserializer> valueDeser, ValueInstantiator valueInstantiator)
{
this(collectionType, valueInstantiator, null, valueDeser, valueDeser, null);
}
@SuppressWarnings("unchecked")
protected StringCollectionDeserializer(JavaType collectionType,
ValueInstantiator valueInstantiator, JsonDeserializer> delegateDeser,
JsonDeserializer> valueDeser,
NullValueProvider nuller, Boolean unwrapSingle)
{
super(collectionType, nuller, unwrapSingle);
_valueDeserializer = (JsonDeserializer) valueDeser;
_valueInstantiator = valueInstantiator;
_delegateDeserializer = (JsonDeserializer) delegateDeser;
}
protected StringCollectionDeserializer withResolved(JsonDeserializer> delegateDeser,
JsonDeserializer> valueDeser,
NullValueProvider nuller, Boolean unwrapSingle)
{
if ((Objects.equals(_unwrapSingle, unwrapSingle)) && (_nullProvider == nuller)
&& (_valueDeserializer == valueDeser) && (_delegateDeserializer == delegateDeser)) {
return this;
}
return new StringCollectionDeserializer(_containerType, _valueInstantiator,
delegateDeser, valueDeser, nuller, unwrapSingle);
}
@Override // since 2.5
public boolean isCachable() {
// 26-Mar-2015, tatu: Important: prevent caching if custom deserializers via annotations
// are involved
return (_valueDeserializer == null) && (_delegateDeserializer == null);
}
@Override // since 2.12
public LogicalType logicalType() {
return LogicalType.Collection;
}
/*
/**********************************************************
/* Validation, post-processing
/**********************************************************
*/
@Override
public JsonDeserializer> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
// May need to resolve types for delegate-based creators:
JsonDeserializer delegate = null;
if (_valueInstantiator != null) {
// [databind#2324]: check both array-delegating and delegating
AnnotatedWithParams delegateCreator = _valueInstantiator.getArrayDelegateCreator();
if (delegateCreator != null) {
JavaType delegateType = _valueInstantiator.getArrayDelegateType(ctxt.getConfig());
delegate = findDeserializer(ctxt, delegateType, property);
} else if ((delegateCreator = _valueInstantiator.getDelegateCreator()) != null) {
JavaType delegateType = _valueInstantiator.getDelegateType(ctxt.getConfig());
delegate = findDeserializer(ctxt, delegateType, property);
}
}
JsonDeserializer> valueDeser = _valueDeserializer;
final JavaType valueType = _containerType.getContentType();
if (valueDeser == null) {
// [databind#125]: May have a content converter
valueDeser = findConvertingContentDeserializer(ctxt, property, valueDeser);
if (valueDeser == null) {
// And we may also need to get deserializer for String
valueDeser = ctxt.findContextualValueDeserializer(valueType, property);
}
} else { // if directly assigned, probably not yet contextual, so:
valueDeser = ctxt.handleSecondaryContextualization(valueDeser, property, valueType);
}
// 11-Dec-2015, tatu: Should we pass basic `Collection.class`, or more refined? Mostly
// comes down to "List vs Collection" I suppose... for now, pass Collection
Boolean unwrapSingle = findFormatFeature(ctxt, property, Collection.class,
JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
NullValueProvider nuller = findContentNullProvider(ctxt, property, valueDeser);
if (isDefaultDeserializer(valueDeser)) {
valueDeser = null;
}
return withResolved(delegate, valueDeser, nuller, unwrapSingle);
}
/*
/**********************************************************
/* ContainerDeserializerBase API
/**********************************************************
*/
@SuppressWarnings("unchecked")
@Override
public JsonDeserializer getContentDeserializer() {
JsonDeserializer> deser = _valueDeserializer;
return (JsonDeserializer) deser;
}
@Override
public ValueInstantiator getValueInstantiator() {
return _valueInstantiator;
}
/*
/**********************************************************
/* JsonDeserializer API
/**********************************************************
*/
@SuppressWarnings("unchecked")
@Override
public Collection deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException
{
if (_delegateDeserializer != null) {
return (Collection) _valueInstantiator.createUsingDelegate(ctxt,
_delegateDeserializer.deserialize(p, ctxt));
}
final Collection result = (Collection) _valueInstantiator.createUsingDefault(ctxt);
return deserialize(p, ctxt, result);
}
@Override
public Collection deserialize(JsonParser p, DeserializationContext ctxt,
Collection result)
throws IOException
{
// Ok: must point to START_ARRAY
if (!p.isExpectedStartArrayToken()) {
return handleNonArray(p, ctxt, result);
}
if (_valueDeserializer != null) {
return deserializeUsingCustom(p, ctxt, result, _valueDeserializer);
}
try {
while (true) {
// First the common case:
String value = p.nextTextValue();
if (value != null) {
result.add(value);
continue;
}
JsonToken t = p.currentToken();
if (t == JsonToken.END_ARRAY) {
break;
}
if (t == JsonToken.VALUE_NULL) {
if (_skipNullValues) {
continue;
}
value = (String) _nullProvider.getNullValue(ctxt);
} else {
value = _parseString(p, ctxt, _nullProvider);
}
result.add(value);
}
} catch (Exception e) {
throw JsonMappingException.wrapWithPath(e, result, result.size());
}
return result;
}
private Collection deserializeUsingCustom(JsonParser p, DeserializationContext ctxt,
Collection result, final JsonDeserializer deser) throws IOException
{
try {
while (true) {
/* 30-Dec-2014, tatu: This may look odd, but let's actually call method
* that suggest we are expecting a String; this helps with some formats,
* notably XML. Note, however, that while we can get String, we can't
* assume that's what we use due to custom deserializer
*/
String value;
if (p.nextTextValue() == null) {
JsonToken t = p.currentToken();
if (t == JsonToken.END_ARRAY) {
break;
}
// Ok: no need to convert Strings, but must recognize nulls
if (t == JsonToken.VALUE_NULL) {
if (_skipNullValues) {
continue;
}
value = (String) _nullProvider.getNullValue(ctxt);
} else {
value = deser.deserialize(p, ctxt);
}
} else {
value = deser.deserialize(p, ctxt);
}
result.add(value);
}
} catch (Exception e) {
throw JsonMappingException.wrapWithPath(e, result, result.size());
}
return result;
}
@Override
public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
TypeDeserializer typeDeserializer) throws IOException {
// In future could check current token... for now this should be enough:
return typeDeserializer.deserializeTypedFromArray(p, ctxt);
}
/**
* Helper method called when current token is not START_ARRAY. Will either
* throw an exception, or try to handle value as if member of implicit
* array, depending on configuration.
*/
@SuppressWarnings("unchecked")
private final Collection handleNonArray(JsonParser p, DeserializationContext ctxt,
Collection result) throws IOException
{
// implicit arrays from single values?
boolean canWrap = (_unwrapSingle == Boolean.TRUE) ||
((_unwrapSingle == null) &&
ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY));
if (!canWrap) {
if (p.hasToken(JsonToken.VALUE_STRING)) {
return _deserializeFromString(p, ctxt);
}
return (Collection) ctxt.handleUnexpectedToken(_containerType, p);
}
// Strings are one of "native" (intrinsic) types, so there's never type deserializer involved
JsonDeserializer valueDes = _valueDeserializer;
JsonToken t = p.currentToken();
String value;
if (t == JsonToken.VALUE_NULL) {
// 03-Feb-2017, tatu: Does this work?
if (_skipNullValues) {
return result;
}
value = (String) _nullProvider.getNullValue(ctxt);
} else {
if (p.hasToken(JsonToken.VALUE_STRING)) {
String textValue = p.getText();
// https://github.com/FasterXML/jackson-dataformat-xml/issues/513
if (textValue.isEmpty()) {
final CoercionAction act = ctxt.findCoercionAction(logicalType(), handledType(),
CoercionInputShape.EmptyString);
if (act != CoercionAction.Fail) {
return (Collection) _deserializeFromEmptyString(p, ctxt, act, handledType(),
"empty String (\"\")");
}
} else if (_isBlank(textValue)) {
final CoercionAction act = ctxt.findCoercionFromBlankString(logicalType(), handledType(),
CoercionAction.Fail);
if (act != CoercionAction.Fail) {
return (Collection) _deserializeFromEmptyString(p, ctxt, act, handledType(),
"blank String (all whitespace)");
}
}
// if coercion failed, we can still add it to a list
}
try {
value = (valueDes == null) ? _parseString(p, ctxt, _nullProvider) : valueDes.deserialize(p, ctxt);
} catch (Exception e) {
throw JsonMappingException.wrapWithPath(e, result, result.size());
}
}
result.add(value);
return result;
}
}