Skip to content

Commit

Permalink
First fix for #622 that seems to work (after minor fixes to test also…
Browse files Browse the repository at this point in the history
…; id class MUST implement #equals() and #hashCode()!)

Will see if polymorphic case would support, and if not, what is needed to support it.
  • Loading branch information
cowtowncoder committed Dec 10, 2014
1 parent e78d39d commit d55cab3
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,24 @@ private final Object vanillaDeserialize(JsonParser p,
}

/**
* General version used when handling needs more advanced
* features.
* General version used when handling needs more advanced features.
*/
@Override
public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException
{
/* 09-Dec-2014, tatu: As per [#622], we need to allow Object Id references
* to come in as JSON Objects as well; but for now assume they will
* be simple, single-prooerty references, which means that we can

This comment has been minimized.

Copy link
@lookfirst

lookfirst Dec 10, 2014

prooerty. =)

This comment has been minimized.

Copy link
@cowtowncoder

cowtowncoder Dec 10, 2014

Author Member

you hadn't heard of those? Not-as-rich properties!

Ok ok, yeah. oR typo.

This comment has been minimized.

Copy link
@lookfirst

lookfirst Dec 10, 2014

😄

* recognize them without having to buffer anything.
* Once again, if we must, we can do more complex handling with buffering,
* but let's only do that if and when that becomes necessary.
*/
if (_objectIdReader != null && _objectIdReader.maySerializeAsObject()) {
if (p.hasTokenId(JsonTokenId.ID_FIELD_NAME)
&& _objectIdReader.isValidReferencePropertyName(p.getCurrentName(), p)) {
return deserializeFromObjectId(p, ctxt);
}
}
if (_nonStandardCreation) {
if (_unwrappedPropertyHandler != null) {
return deserializeWithUnwrapped(p, ctxt);
Expand All @@ -276,14 +288,14 @@ public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) t
if (_needViewProcesing) {
Class<?> view = ctxt.getActiveView();
if (view != null) {
return deserializeWithView(jp, ctxt, bean, view);
return deserializeWithView(p, ctxt, bean, view);
}
}
*/
return bean;
}
final Object bean = _valueInstantiator.createUsingDefault(ctxt);
// [databind#631]: Assign current value, to be accessible by custom serializers
// [databind#631]: Assign current value, to be accessible by custom deserializers
p.setCurrentValue(bean);
if (p.canReadObjectId()) {
Object id = p.getObjectId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -926,34 +926,34 @@ public void replaceProperty(SettableBeanProperty original,
* General version used when handling needs more advanced
* features.
*/
public abstract Object deserializeFromObject(JsonParser jp, DeserializationContext ctxt)
public abstract Object deserializeFromObject(JsonParser p, DeserializationContext ctxt)
throws IOException;

@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
TypeDeserializer typeDeserializer)
throws IOException
{
// 16-Feb-2012, tatu: ObjectId may be used as well... need to check that first
if (_objectIdReader != null) {
// 05-Aug-2013, tatu: May use native Object Id
if (jp.canReadObjectId()) {
Object id = jp.getObjectId();
if (p.canReadObjectId()) {
Object id = p.getObjectId();
if (id != null) {
Object ob = typeDeserializer.deserializeTypedFromObject(jp, ctxt);
return _handleTypedObjectId(jp, ctxt, ob, id);
Object ob = typeDeserializer.deserializeTypedFromObject(p, ctxt);
return _handleTypedObjectId(p, ctxt, ob, id);
}
}
// or, Object Ids Jackson explicitly sets
JsonToken t = jp.getCurrentToken();
JsonToken t = p.getCurrentToken();
// for now (2.2.x) we only allow scalar types (Strings, integral numbers):
// NOTE: may need to allow handling of structured values in future for JSOG
if (t != null && t.isScalarValue()) {
return deserializeFromObjectId(jp, ctxt);
if (t != null && (t.isScalarValue() || _objectIdReader.maySerializeAsObject())) {
return deserializeFromObjectId(p, ctxt);
}
}
// In future could check current token... for now this should be enough:
return typeDeserializer.deserializeTypedFromObject(jp, ctxt);
return typeDeserializer.deserializeTypedFromObject(p, ctxt);
}

/**
Expand All @@ -964,7 +964,7 @@ public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
*/
protected Object _handleTypedObjectId(JsonParser jp, DeserializationContext ctxt,
Object pojo, Object rawId)
throws IOException, JsonProcessingException
throws IOException
{
/* 07-Aug-2013, tatu: One more challenge: type of id may not be type
* of property we are expecting later on; specifically, numeric ids
Expand Down Expand Up @@ -1034,7 +1034,7 @@ protected Object _convertObjectId(JsonParser jp, DeserializationContext ctxt,
protected Object deserializeWithObjectId(JsonParser jp, DeserializationContext ctxt) throws IOException {
return deserializeFromObject(jp, ctxt);
}

/**
* Method called in cases where it looks like we got an Object Id
* to parse and use as a reference.
Expand All @@ -1054,7 +1054,7 @@ protected Object deserializeFromObjectId(JsonParser jp, DeserializationContext c

protected Object deserializeFromObjectUsingNonDefault(JsonParser jp,
DeserializationContext ctxt) throws IOException
{
{
if (_delegateDeserializer != null) {
return _valueInstantiator.createUsingDelegate(ctxt,
_delegateDeserializer.deserialize(jp, ctxt));
Expand Down Expand Up @@ -1115,82 +1115,82 @@ public Object deserializeFromNumber(JsonParser jp, DeserializationContext ctxt)
}
return bean;
}
throw ctxt.instantiationException(getBeanClass(), "no suitable creator method found to deserialize from JSON integer number");
throw ctxt.instantiationException(handledType(), "no suitable creator method found to deserialize from JSON integer number");
}

public Object deserializeFromString(JsonParser jp, DeserializationContext ctxt) throws IOException
public Object deserializeFromString(JsonParser p, DeserializationContext ctxt) throws IOException
{
// First things first: id Object Id is used, most likely that's it
if (_objectIdReader != null) {
return deserializeFromObjectId(jp, ctxt);
return deserializeFromObjectId(p, ctxt);
}

/* Bit complicated if we have delegating creator; may need to use it,
* or might not...
*/
if (_delegateDeserializer != null) {
if (!_valueInstantiator.canCreateFromString()) {
Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(jp, ctxt));
Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
return bean;
}
}
return _valueInstantiator.createFromString(ctxt, jp.getText());
return _valueInstantiator.createFromString(ctxt, p.getText());
}

/**
* Method called to deserialize POJO value from a JSON floating-point
* number.
*/
@SuppressWarnings("incomplete-switch")
public Object deserializeFromDouble(JsonParser jp, DeserializationContext ctxt) throws IOException
public Object deserializeFromDouble(JsonParser p, DeserializationContext ctxt) throws IOException
{
switch (jp.getNumberType()) {
switch (p.getNumberType()) {
case FLOAT: // no separate methods for taking float...
case DOUBLE:
if (_delegateDeserializer != null) {
if (!_valueInstantiator.canCreateFromDouble()) {
Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(jp, ctxt));
Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
return bean;
}
}
return _valueInstantiator.createFromDouble(ctxt, jp.getDoubleValue());
return _valueInstantiator.createFromDouble(ctxt, p.getDoubleValue());
}
// actually, could also be BigDecimal, so:
if (_delegateDeserializer != null) {
return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(jp, ctxt));
return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
}
throw ctxt.instantiationException(getBeanClass(), "no suitable creator method found to deserialize from JSON floating-point number");
throw ctxt.instantiationException(handledType(), "no suitable creator method found to deserialize from JSON floating-point number");
}

/**
* Method called to deserialize POJO value from a JSON boolean value (true, false)
*/
public Object deserializeFromBoolean(JsonParser jp, DeserializationContext ctxt) throws IOException
public Object deserializeFromBoolean(JsonParser p, DeserializationContext ctxt) throws IOException
{
if (_delegateDeserializer != null) {
if (!_valueInstantiator.canCreateFromBoolean()) {
Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(jp, ctxt));
Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
return bean;
}
}
boolean value = (jp.getCurrentToken() == JsonToken.VALUE_TRUE);
boolean value = (p.getCurrentToken() == JsonToken.VALUE_TRUE);
return _valueInstantiator.createFromBoolean(ctxt, value);
}

public Object deserializeFromArray(JsonParser jp, DeserializationContext ctxt) throws IOException
public Object deserializeFromArray(JsonParser p, DeserializationContext ctxt) throws IOException
{
if (_delegateDeserializer != null) {
try {
Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(jp, ctxt));
Object bean = _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
Expand All @@ -1199,18 +1199,18 @@ public Object deserializeFromArray(JsonParser jp, DeserializationContext ctxt) t
wrapInstantiationProblem(e, ctxt);
}
} else if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
JsonToken t = jp.nextToken();
JsonToken t = p.nextToken();
if (t == JsonToken.END_ARRAY && ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
return null;
}
final Object value = deserialize(jp, ctxt);
if (jp.nextToken() != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
final Object value = deserialize(p, ctxt);
if (p.nextToken() != JsonToken.END_ARRAY) {
throw ctxt.wrongTokenException(p, JsonToken.END_ARRAY,
"Attempted to unwrap single value array for single '" + _valueClass.getName() + "' value but there was more than a single value in the array");
}
return value;
} else if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
JsonToken t = jp.nextToken();
JsonToken t = p.nextToken();
if (t == JsonToken.END_ARRAY) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
import com.fasterxml.jackson.annotation.ObjectIdGenerator;
import com.fasterxml.jackson.annotation.ObjectIdResolver;
import com.fasterxml.jackson.annotation.SimpleObjectIdResolver;

import com.fasterxml.jackson.core.JsonParser;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.SettableBeanProperty;

Expand Down Expand Up @@ -97,6 +95,36 @@ public JsonDeserializer<Object> getDeserializer() {
public JavaType getIdType() {
return _idType;
}

/**
* Convenience method, equivalent to calling:
*<code>
* readerInstance.generator.maySerializeAsObject();
*</code>
* and used to determine whether Object Ids handled by the underlying
* generator may be in form of (JSON) Objects.
* Used for optimizing handling in cases where method returns false.
*
* @since 2.5
*/
public boolean maySerializeAsObject() {
return generator.maySerializeAsObject();
}

/**
* Convenience method, equivalent to calling:
*<code>
* readerInstance.generator.isValidReferencePropertyName(name, parser);
*</code>
* and used to determine whether Object Ids handled by the underlying
* generator may be in form of (JSON) Objects.
* Used for optimizing handling in cases where method returns false.
*
* @since 2.5
*/
public boolean isValidReferencePropertyName(String name, JsonParser parser) {
return generator.isValidReferencePropertyName(name, parser);
}

/**
* Method called to read value that is expected to be an Object Reference
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ public final class ObjectIdValueProperty

protected final ObjectIdReader _objectIdReader;

@Deprecated // since 2.2
public ObjectIdValueProperty(ObjectIdReader objectIdReader) {
this(objectIdReader, PropertyMetadata.STD_REQUIRED);
}

public ObjectIdValueProperty(ObjectIdReader objectIdReader,
PropertyMetadata metadata)
{
Expand Down
Loading

0 comments on commit d55cab3

Please sign in to comment.