Skip to content

Commit

Permalink
minor clean up of builder-based deserializer; add better error checki…
Browse files Browse the repository at this point in the history
…ng, reporting
  • Loading branch information
cowtowncoder committed Oct 26, 2016
1 parent 7b7b54e commit 423db74
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 96 deletions.
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ public JsonDeserializer<?> buildBuilderBased(JavaType valueType,
} }


return new BuilderBasedDeserializer(this, return new BuilderBasedDeserializer(this,
_beanDesc, propertyMap, _backRefProperties, _ignorableProps, _ignoreAllUnknown, _beanDesc, valueType, propertyMap, _backRefProperties, _ignorableProps, _ignoreAllUnknown,
anyViews); anyViews);
} }


Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ public class BuilderBasedDeserializer
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;


protected final AnnotatedMethod _buildMethod; protected final AnnotatedMethod _buildMethod;

/**
* Type that the builder will produce, target type; as opposed to
* `handledType()` which refers to Builder class.
*
* @since 2.9
*/
protected final JavaType _targetType;


/* /*
/********************************************************** /**********************************************************
Expand All @@ -37,13 +45,14 @@ public class BuilderBasedDeserializer
* Constructor used by {@link BeanDeserializerBuilder}. * Constructor used by {@link BeanDeserializerBuilder}.
*/ */
public BuilderBasedDeserializer(BeanDeserializerBuilder builder, public BuilderBasedDeserializer(BeanDeserializerBuilder builder,
BeanDescription beanDesc, BeanDescription beanDesc, JavaType targetType,
BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs, BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs,
Set<String> ignorableProps, boolean ignoreAllUnknown, Set<String> ignorableProps, boolean ignoreAllUnknown,
boolean hasViews) boolean hasViews)
{ {
super(builder, beanDesc, properties, backRefs, super(builder, beanDesc, properties, backRefs,
ignorableProps, ignoreAllUnknown, hasViews); ignorableProps, ignoreAllUnknown, hasViews);
_targetType = targetType;
_buildMethod = builder.getBuildMethod(); _buildMethod = builder.getBuildMethod();
// 05-Mar-2012, tatu: Can not really make Object Ids work with builders, not yet anyway // 05-Mar-2012, tatu: Can not really make Object Ids work with builders, not yet anyway
if (_objectIdReader != null) { if (_objectIdReader != null) {
Expand All @@ -52,6 +61,21 @@ public BuilderBasedDeserializer(BeanDeserializerBuilder builder,
} }
} }


/**
* @deprecated Since 2.9
*/
@Deprecated
public BuilderBasedDeserializer(BeanDeserializerBuilder builder,
BeanDescription beanDesc,
BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs,
Set<String> ignorableProps, boolean ignoreAllUnknown,
boolean hasViews)
{
this(builder, beanDesc,
beanDesc.getType(), // Wrong! But got no access via `BeanDeserializerBuilder`
properties, backRefs, ignorableProps, ignoreAllUnknown, hasViews);
}

/** /**
* Copy-constructor that can be used by sub-classes to allow * Copy-constructor that can be used by sub-classes to allow
* copy-on-write styling copying of settings of an existing instance. * copy-on-write styling copying of settings of an existing instance.
Expand All @@ -65,26 +89,31 @@ protected BuilderBasedDeserializer(BuilderBasedDeserializer src, boolean ignoreA
{ {
super(src, ignoreAllUnknown); super(src, ignoreAllUnknown);
_buildMethod = src._buildMethod; _buildMethod = src._buildMethod;
_targetType = src._targetType;
} }


protected BuilderBasedDeserializer(BuilderBasedDeserializer src, NameTransformer unwrapper) { protected BuilderBasedDeserializer(BuilderBasedDeserializer src, NameTransformer unwrapper) {
super(src, unwrapper); super(src, unwrapper);
_buildMethod = src._buildMethod; _buildMethod = src._buildMethod;
_targetType = src._targetType;
} }


public BuilderBasedDeserializer(BuilderBasedDeserializer src, ObjectIdReader oir) { public BuilderBasedDeserializer(BuilderBasedDeserializer src, ObjectIdReader oir) {
super(src, oir); super(src, oir);
_buildMethod = src._buildMethod; _buildMethod = src._buildMethod;
_targetType = src._targetType;
} }


public BuilderBasedDeserializer(BuilderBasedDeserializer src, Set<String> ignorableProps) { public BuilderBasedDeserializer(BuilderBasedDeserializer src, Set<String> ignorableProps) {
super(src, ignorableProps); super(src, ignorableProps);
_buildMethod = src._buildMethod; _buildMethod = src._buildMethod;
_targetType = src._targetType;
} }


public BuilderBasedDeserializer(BuilderBasedDeserializer src, BeanPropertyMap props) { public BuilderBasedDeserializer(BuilderBasedDeserializer src, BeanPropertyMap props) {
super(src, props); super(src, props);
_buildMethod = src._buildMethod; _buildMethod = src._buildMethod;
_targetType = src._targetType;
} }


@Override @Override
Expand Down Expand Up @@ -115,15 +144,15 @@ public BeanDeserializerBase withBeanProperties(BeanPropertyMap props) {
@Override @Override
protected BeanDeserializerBase asArrayDeserializer() { protected BeanDeserializerBase asArrayDeserializer() {
SettableBeanProperty[] props = _beanProperties.getPropertiesInInsertionOrder(); SettableBeanProperty[] props = _beanProperties.getPropertiesInInsertionOrder();
return new BeanAsArrayBuilderDeserializer(this, props, _buildMethod); return new BeanAsArrayBuilderDeserializer(this, _targetType, props, _buildMethod);
} }


/* /*
/********************************************************** /**********************************************************
/* JsonDeserializer implementation /* JsonDeserializer implementation
/********************************************************** /**********************************************************
*/ */

protected final Object finishBuild(DeserializationContext ctxt, Object builder) protected final Object finishBuild(DeserializationContext ctxt, Object builder)
throws IOException throws IOException
{ {
Expand All @@ -137,47 +166,43 @@ protected final Object finishBuild(DeserializationContext ctxt, Object builder)
return wrapInstantiationProblem(e, ctxt); return wrapInstantiationProblem(e, ctxt);
} }
} }

/** /**
* Main deserialization method for bean-based objects (POJOs). * Main deserialization method for bean-based objects (POJOs).
*/ */
@Override @Override
public final Object deserialize(JsonParser p, DeserializationContext ctxt) public final Object deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException throws IOException
{ {
JsonToken t = p.getCurrentToken();

// common case first: // common case first:
if (t == JsonToken.START_OBJECT) { if (p.isExpectedStartObjectToken()) {
t = p.nextToken(); JsonToken t = p.nextToken();
if (_vanillaProcessing) { if (_vanillaProcessing) {
return finishBuild(ctxt, vanillaDeserialize(p, ctxt, t)); return finishBuild(ctxt, vanillaDeserialize(p, ctxt, t));
} }
Object builder = deserializeFromObject(p, ctxt); Object builder = deserializeFromObject(p, ctxt);
return finishBuild(ctxt, builder); return finishBuild(ctxt, builder);
} }
// and then others, generally requiring use of @JsonCreator // and then others, generally requiring use of @JsonCreator
if (t != null) { switch (p.getCurrentTokenId()) {
switch (t) { case JsonTokenId.ID_STRING:
case VALUE_STRING: return finishBuild(ctxt, deserializeFromString(p, ctxt));
return finishBuild(ctxt, deserializeFromString(p, ctxt)); case JsonTokenId.ID_NUMBER_INT:
case VALUE_NUMBER_INT: return finishBuild(ctxt, deserializeFromNumber(p, ctxt));
return finishBuild(ctxt, deserializeFromNumber(p, ctxt)); case JsonTokenId.ID_NUMBER_FLOAT:
case VALUE_NUMBER_FLOAT: return finishBuild(ctxt, deserializeFromDouble(p, ctxt));
return finishBuild(ctxt, deserializeFromDouble(p, ctxt)); case JsonTokenId.ID_EMBEDDED_OBJECT:
case VALUE_EMBEDDED_OBJECT: return p.getEmbeddedObject();
return p.getEmbeddedObject(); case JsonTokenId.ID_TRUE:
case VALUE_TRUE: case JsonTokenId.ID_FALSE:
case VALUE_FALSE: return finishBuild(ctxt, deserializeFromBoolean(p, ctxt));
return finishBuild(ctxt, deserializeFromBoolean(p, ctxt)); case JsonTokenId.ID_START_ARRAY:
case START_ARRAY: // these only work if there's a (delegating) creator...
// these only work if there's a (delegating) creator... return finishBuild(ctxt, deserializeFromArray(p, ctxt));
return finishBuild(ctxt, deserializeFromArray(p, ctxt)); case JsonTokenId.ID_FIELD_NAME:
case FIELD_NAME: case JsonTokenId.ID_END_OBJECT:
case END_OBJECT: return finishBuild(ctxt, deserializeFromObject(p, ctxt));
return finishBuild(ctxt, deserializeFromObject(p, ctxt)); default:
default:
}
} }
return ctxt.handleUnexpectedToken(handledType(), p); return ctxt.handleUnexpectedToken(handledType(), p);
} }
Expand All @@ -189,15 +214,24 @@ public final Object deserialize(JsonParser p, DeserializationContext ctxt)
*/ */
@Override @Override
public Object deserialize(JsonParser p, DeserializationContext ctxt, public Object deserialize(JsonParser p, DeserializationContext ctxt,
Object builder) Object value) throws IOException
throws IOException
{ {
/* Important: we call separate method which does NOT call // 26-Oct-2016, tatu: I can not see any of making this actually
* 'finishBuild()', to avoid problems with recursion // work correctly, so let's indicate problem right away
*/ JavaType valueType = _targetType;
return finishBuild(ctxt, _deserialize(p, ctxt, builder)); // Did they try to give us builder?
Class<?> builderRawType = handledType();
Class<?> instRawType = value.getClass();
if (builderRawType.isAssignableFrom(instRawType)) {
return ctxt.reportBadDefinition(valueType, String.format(
"Deserialization of %s by passing existing Builder (%s) instance not supported",
valueType, builderRawType.getName()));
}
return ctxt.reportBadDefinition(valueType, String.format(
"Deserialization of %s by passing existing instance (of %s) not supported",
valueType, instRawType.getName()));
} }

/* /*
/********************************************************** /**********************************************************
/* Concrete deserialization methods /* Concrete deserialization methods
Expand All @@ -206,7 +240,7 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt,


protected final Object _deserialize(JsonParser p, protected final Object _deserialize(JsonParser p,
DeserializationContext ctxt, Object builder) DeserializationContext ctxt, Object builder)
throws IOException, JsonProcessingException throws IOException
{ {
if (_injectables != null) { if (_injectables != null) {
injectValues(ctxt, builder); injectValues(ctxt, builder);
Expand Down Expand Up @@ -246,14 +280,14 @@ protected final Object _deserialize(JsonParser p,
} }
return builder; return builder;
} }

/** /**
* Streamlined version that is only used when no "special" * Streamlined version that is only used when no "special"
* features are enabled. * features are enabled.
*/ */
private final Object vanillaDeserialize(JsonParser p, private final Object vanillaDeserialize(JsonParser p,
DeserializationContext ctxt, JsonToken t) DeserializationContext ctxt, JsonToken t)
throws IOException, JsonProcessingException throws IOException
{ {
Object bean = _valueInstantiator.createUsingDefault(ctxt); Object bean = _valueInstantiator.createUsingDefault(ctxt);
for (; p.getCurrentToken() != JsonToken.END_OBJECT; p.nextToken()) { for (; p.getCurrentToken() != JsonToken.END_OBJECT; p.nextToken()) {
Expand All @@ -280,7 +314,7 @@ private final Object vanillaDeserialize(JsonParser p,
*/ */
@Override @Override
public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException throws IOException
{ {
if (_nonStandardCreation) { if (_nonStandardCreation) {
if (_unwrappedPropertyHandler != null) { if (_unwrappedPropertyHandler != null) {
Expand Down Expand Up @@ -331,7 +365,7 @@ public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt)
@SuppressWarnings("resource") @SuppressWarnings("resource")
protected final Object _deserializeUsingPropertyBased(final JsonParser p, protected final Object _deserializeUsingPropertyBased(final JsonParser p,
final DeserializationContext ctxt) final DeserializationContext ctxt)
throws IOException, JsonProcessingException throws IOException
{ {
final PropertyBasedCreator creator = _propertyBasedCreator; final PropertyBasedCreator creator = _propertyBasedCreator;
PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader); PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader);
Expand Down Expand Up @@ -423,7 +457,7 @@ protected final Object _deserializeUsingPropertyBased(final JsonParser p,


protected final Object deserializeWithView(JsonParser p, DeserializationContext ctxt, protected final Object deserializeWithView(JsonParser p, DeserializationContext ctxt,
Object bean, Class<?> activeView) Object bean, Class<?> activeView)
throws IOException, JsonProcessingException throws IOException
{ {
JsonToken t = p.getCurrentToken(); JsonToken t = p.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
Expand Down Expand Up @@ -460,7 +494,7 @@ protected final Object deserializeWithView(JsonParser p, DeserializationContext
*/ */
@SuppressWarnings("resource") @SuppressWarnings("resource")
protected Object deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt) protected Object deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException throws IOException
{ {
if (_delegateDeserializer != null) { if (_delegateDeserializer != null) {
return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt)); return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
Expand Down Expand Up @@ -520,7 +554,7 @@ protected Object deserializeWithUnwrapped(JsonParser p, DeserializationContext c
@SuppressWarnings("resource") @SuppressWarnings("resource")
protected Object deserializeWithUnwrapped(JsonParser p, protected Object deserializeWithUnwrapped(JsonParser p,
DeserializationContext ctxt, Object bean) DeserializationContext ctxt, Object bean)
throws IOException, JsonProcessingException throws IOException
{ {
JsonToken t = p.getCurrentToken(); JsonToken t = p.getCurrentToken();
if (t == JsonToken.START_OBJECT) { if (t == JsonToken.START_OBJECT) {
Expand Down Expand Up @@ -565,7 +599,7 @@ protected Object deserializeWithUnwrapped(JsonParser p,
@SuppressWarnings("resource") @SuppressWarnings("resource")
protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p, protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p,
DeserializationContext ctxt) DeserializationContext ctxt)
throws IOException, JsonProcessingException throws IOException
{ {
final PropertyBasedCreator creator = _propertyBasedCreator; final PropertyBasedCreator creator = _propertyBasedCreator;
PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader); PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader);
Expand Down Expand Up @@ -649,7 +683,7 @@ protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p,
*/ */


protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt) protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException throws IOException
{ {
if (_propertyBasedCreator != null) { if (_propertyBasedCreator != null) {
return deserializeUsingPropertyBasedWithExternalTypeId(p, ctxt); return deserializeUsingPropertyBasedWithExternalTypeId(p, ctxt);
Expand All @@ -659,7 +693,7 @@ protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationCont


protected Object deserializeWithExternalTypeId(JsonParser p, protected Object deserializeWithExternalTypeId(JsonParser p,
DeserializationContext ctxt, Object bean) DeserializationContext ctxt, Object bean)
throws IOException, JsonProcessingException throws IOException
{ {
final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null; final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
final ExternalTypeHandler ext = _externalTypeIdHandler.start(); final ExternalTypeHandler ext = _externalTypeIdHandler.start();
Expand Down Expand Up @@ -712,9 +746,12 @@ protected Object deserializeWithExternalTypeId(JsonParser p,


protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p,
DeserializationContext ctxt) DeserializationContext ctxt)
throws IOException, JsonProcessingException throws IOException
{ {
// !!! 04-Mar-2012, TODO: Need to fix -- will not work as is... // !!! 04-Mar-2012, TODO: Need to fix -- will not work as is...
throw new IllegalStateException("Deserialization with Builder, External type id, @JsonCreator not yet implemented"); JavaType t = _targetType;
return ctxt.reportBadDefinition(t, String.format(
"Deserialization (of %s) with Builder, External type id, @JsonCreator not yet implemented",
t));
} }
} }
Loading

0 comments on commit 423db74

Please sign in to comment.