Skip to content

Commit

Permalink
Initial fix for issue FasterXML#351, handle simple case.
Browse files Browse the repository at this point in the history
  • Loading branch information
Pascal Gélinas committed Nov 26, 2013
1 parent 76bf34f commit 82d08ed
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerator;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;

import com.fasterxml.jackson.core.*;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.impl.*;
import com.fasterxml.jackson.databind.deser.std.StdDelegatingDeserializer;
Expand Down Expand Up @@ -450,6 +448,8 @@ public void resolve(DeserializationContext ctxt)
}
// [JACKSON-235]: need to link managed references with matching back references
prop = _resolveManagedReferenceProperty(ctxt, prop);

prop = _resolvedObjectIdProperty(ctxt, prop);
// [JACKSON-132]: support unwrapped values (via @JsonUnwrapped)
SettableBeanProperty u = _resolveUnwrappedProperty(ctxt, prop);
if (u != null) {
Expand Down Expand Up @@ -653,6 +653,17 @@ protected SettableBeanProperty _resolveManagedReferenceProperty(DeserializationC
_classAnnotations, isContainer);
}

protected SettableBeanProperty _resolvedObjectIdProperty(DeserializationContext ctxt, SettableBeanProperty prop) {
ObjectIdInfo objectIdInfo = prop.getObjectIdInfo();
JsonDeserializer<Object> valueDeser = prop.getValueDeserializer();
ObjectIdReader objectIdReader = valueDeser.getObjectIdReader();
if (objectIdInfo == null && objectIdReader == null) { return prop; }

// TODO handle container-style
// boolean isContainer = prop.getType().isContainerType();
return new ObjectIdReference(prop, objectIdInfo);
}

/**
* Helper method called to see if given property might be so-called unwrapped
* property: these require special handling.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import com.fasterxml.jackson.annotation.ObjectIdGenerator;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig;
Expand Down Expand Up @@ -781,6 +780,10 @@ protected SettableBeanProperty constructSettableProperty(DeserializationContext
if (ref != null && ref.isManagedReference()) {
prop.setManagedReferenceName(ref.getName());
}
ObjectIdInfo objectIdInfo = propDef.findObjectIdInfo();
if(objectIdInfo != null){
prop.setObjectIdInfo(objectIdInfo);
}
return prop;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.fasterxml.jackson.databind.deser.impl.NullProvider;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import com.fasterxml.jackson.databind.introspect.ObjectIdInfo;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fasterxml.jackson.databind.util.Annotations;
Expand Down Expand Up @@ -106,6 +107,13 @@ public abstract class SettableBeanProperty
*/
protected String _managedReferenceName;

/**
* This is the information for object identity associated with the property.
* <p>
* TODO: should try to make immutable.
*/
protected ObjectIdInfo _objectIdInfo;

/**
* Helper object used for checking whether this property is to
* be included in the active view, if property is view-specific;
Expand All @@ -124,7 +132,7 @@ public abstract class SettableBeanProperty
* TODO: should try to make immutable if at all possible
*/
protected int _propertyIndex = -1;

/*
/**********************************************************
/* Life-cycle (construct & configure)
Expand Down Expand Up @@ -316,7 +324,11 @@ public SettableBeanProperty withName(String simpleName) {
public void setManagedReferenceName(String n) {
_managedReferenceName = n;
}


public void setObjectIdInfo(ObjectIdInfo objectIdInfo) {
_objectIdInfo = objectIdInfo;
}

public void setViews(Class<?>[] views) {
if (views == null) {
_viewMatcher = null;
Expand Down Expand Up @@ -399,6 +411,8 @@ protected final Class<?> getDeclaringClass() {

public String getManagedReferenceName() { return _managedReferenceName; }

public ObjectIdInfo getObjectIdInfo() { return _objectIdInfo; }

public boolean hasValueDeserializer() {
return (_valueDeserializer != null) && (_valueDeserializer != MISSING_VALUE_DESERIALIZER);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package com.fasterxml.jackson.databind.deser.impl;

import java.io.IOException;
import java.lang.annotation.Annotation;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.PropertyName;
import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.introspect.ObjectIdInfo;

public class ObjectIdReference extends SettableBeanProperty {
private static final long serialVersionUID = 8465266677345565407L;
private static final Object UNRESOLVED = new Object();
private SettableBeanProperty _forward;
private ObjectIdInfo _objectIdInfo;

public ObjectIdReference(SettableBeanProperty forward, ObjectIdInfo objectIdInfo) {
super(forward.getFullName(),
forward.getType(),
forward.getWrapperName(),
forward.getValueTypeDeserializer(),
null,
forward.getMetadata());
_forward = forward;
_objectIdInfo = objectIdInfo;
}

public ObjectIdReference(ObjectIdReference src, JsonDeserializer<?> deser) {
super(src, deser);
_forward = src._forward;
_objectIdInfo = src._objectIdInfo;
}

public ObjectIdReference(ObjectIdReference src, PropertyName newName) {
super(src, newName);
_forward = src._forward;
_objectIdInfo = src._objectIdInfo;
}

@Override
public SettableBeanProperty withValueDeserializer(JsonDeserializer<?> deser) {
return new ObjectIdReference(this, deser);
}

@Override
public SettableBeanProperty withName(PropertyName newName) {
return new ObjectIdReference(this, newName);
}

@Override
public <A extends Annotation> A getAnnotation(Class<A> acls) {
return _forward.getAnnotation(acls);
}

@Override
public AnnotatedMember getMember() {
return _forward.getMember();
}

@Override
public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt, Object instance) throws IOException,
JsonProcessingException {
set(instance, _deserialize(jp, ctxt, instance));
}

@Override
public Object deserializeSetAndReturn(JsonParser jp, DeserializationContext ctxt, Object instance)
throws IOException, JsonProcessingException {
return setAndReturn(instance, _deserialize(jp, ctxt, instance));
}

private Object _deserialize(JsonParser jp, DeserializationContext ctxt, Object instance) throws JsonProcessingException, IOException {
if(_objectIdInfo != null &&_objectIdInfo.getAlwaysAsId()){
return deserializeFromObjectId(jp, ctxt, instance);
}

JsonToken currentToken = jp.getCurrentToken();
if(currentToken == JsonToken.VALUE_STRING || currentToken == JsonToken.VALUE_NUMBER_INT){
return deserializeFromObjectId(jp, ctxt, instance);
}
return _forward.deserialize(jp, ctxt);
}

protected Object deserializeFromObjectId(JsonParser jp, DeserializationContext ctxt, Object instance) throws IOException,
JsonProcessingException {
ObjectIdReader reader = _forward.getValueDeserializer().getObjectIdReader();
Object id = reader.getDeserializer().deserialize(jp, ctxt);
ReadableObjectId roid = ctxt.findObjectId(id, reader.generator);
// do we have it resolved?
Object pojo = roid.item;
if (pojo == null) { // not yet; should wait...
roid.appendReferring(instance, _forward);
return UNRESOLVED;
}
return pojo;
}

@Override
public void set(Object instance, Object value) throws IOException {
if(value == UNRESOLVED) return;
_forward.set(instance, value);
}

@Override
public Object setAndReturn(Object instance, Object value) throws IOException {
if(value== UNRESOLVED){
return null;
}
return _forward.setAndReturn(instance, value);
}
}

0 comments on commit 82d08ed

Please sign in to comment.