diff options
5 files changed, 22 insertions, 74 deletions
diff --git a/release-notes/VERSION b/release-notes/VERSION index 8f1281f13..f81637eca 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -8,6 +8,7 @@ Description: Fixes: +* [JACKSON-368]: Problems with managed references, abstract types * [JACKSON-711]: Delegating @JsonCreator did not work with Injectable values * [JACKSON-798]: Problem with external type id, creators (reported by Casey L) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/AbstractDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/AbstractDeserializer.java index 17ef72762..b663b8069 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/AbstractDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/AbstractDeserializer.java @@ -1,6 +1,7 @@ package com.fasterxml.jackson.databind.deser; import java.io.IOException; +import java.util.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; @@ -22,6 +23,8 @@ public class AbstractDeserializer protected final JavaType _baseType; protected final ObjectIdReader _objectIdReader; + + protected final Map<String, SettableBeanProperty> _backRefProperties; // support for "native" types, which require special care: @@ -30,11 +33,13 @@ public class AbstractDeserializer protected final boolean _acceptInt; protected final boolean _acceptDouble; - public AbstractDeserializer(JavaType bt, ObjectIdReader oir) + public AbstractDeserializer(BeanDeserializerBuilder builder, + BeanDescription beanDesc, Map<String, SettableBeanProperty> backRefProps) { - _baseType = bt; - _objectIdReader = oir; - Class<?> cls = bt.getRawClass(); + _baseType = beanDesc.getType(); + _objectIdReader = builder.getObjectIdReader(); + _backRefProperties = backRefProps; + Class<?> cls = _baseType.getRawClass(); _acceptString = cls.isAssignableFrom(String.class); _acceptBoolean = (cls == Boolean.TYPE) || cls.isAssignableFrom(Boolean.class); _acceptInt = (cls == Integer.TYPE) || cls.isAssignableFrom(Integer.class); @@ -60,6 +65,15 @@ public class AbstractDeserializer return _objectIdReader; } + /** + * Method called by <code>BeanDeserializer</code> to resolve back reference + * part of managed references. + */ + public SettableBeanProperty findBackReference(String logicalName) + { + return (_backRefProperties == null) ? null : _backRefProperties.get(logicalName); + } + /* /********************************************************** /* Deserializer implementation diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java index 937124686..7ef28e30c 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java @@ -559,8 +559,8 @@ public abstract class BeanDeserializerBase } backProp = ((BeanDeserializerBase) contentDeser).findBackReference(refName); isContainer = true; - } else if (valueDeser instanceof AbstractDeserializer) { // [JACKSON-368]: not easy to fix, alas - throw new IllegalArgumentException("Can not handle managed/back reference for abstract types (property "+_beanType.getRawClass().getName()+"."+prop.getName()+")"); + } else if (valueDeser instanceof AbstractDeserializer) { + backProp = ((AbstractDeserializer) valueDeser).findBackReference(refName); } else { throw new IllegalArgumentException("Can not handle managed/back reference '"+refName +"': type for value deserializer is not BeanDeserializer or ContainerDeserializerBase, but " diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java index 7366cae95..f794e46b9 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java @@ -342,7 +342,7 @@ public class BeanDeserializerBuilder */ public AbstractDeserializer buildAbstract() { - return new AbstractDeserializer(_beanDesc.getType(), _objectIdReader); + return new AbstractDeserializer(this, _beanDesc, _backRefProperties); } /** diff --git a/src/test/java/com/fasterxml/jackson/failing/TestAbstractParentChild.java b/src/test/java/com/fasterxml/jackson/failing/TestAbstractParentChild.java deleted file mode 100644 index ec4daa331..000000000 --- a/src/test/java/com/fasterxml/jackson/failing/TestAbstractParentChild.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.fasterxml.jackson.failing; - - -import com.fasterxml.jackson.annotation.*; -import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; -import com.fasterxml.jackson.databind.BaseMapTest; -import com.fasterxml.jackson.databind.ObjectMapper; - -/** - * Currently (1.8) parent/child dependencies do not work in - * combination with abstract types; they should, but fixing this - * require major changes to handling of both features. - */ -public class TestAbstractParentChild extends BaseMapTest -{ - @JsonTypeInfo(use=Id.NAME) - @JsonSubTypes({@JsonSubTypes.Type(ConcreteNode.class)}) - static abstract class AbstractNode - { - public String id; - - @JsonManagedReference public AbstractNode next; - @JsonBackReference public AbstractNode prev; - } - - @JsonTypeName("concrete") - static class ConcreteNode extends AbstractNode { - public ConcreteNode() { } - public ConcreteNode(String id) { this.id = id; } - } - - /* - /********************************************************** - /* Unit tests - /********************************************************** - */ - - /* 22-Sep-2010, tatu: This is for [JACKSON-368]. Easy to reproduce the issue, - * but alas not nearly as easy to resolve. Problem is that AbstractDeserializer - * has little knowledge of actual type, and so linkage can not be made statically. - */ - public void testAbstract() throws Exception - { - AbstractNode parent = new ConcreteNode("p"); - AbstractNode child = new ConcreteNode("c"); - parent.next = child; - child.prev = parent; - - // serialization ought to be ok - ObjectMapper mapper = new ObjectMapper(); - String json = mapper.writeValueAsString(parent); - - AbstractNode root = null; - try { - root = mapper.readValue(json, AbstractNode.class); - } catch (IllegalArgumentException e) { - fail("Did not expect an exception; got: "+e.getMessage()); - } - assertEquals(ConcreteNode.class, root.getClass()); - assertEquals("p", root.id); - assertNull(root.prev); - AbstractNode leaf = root.next; - assertNotNull(leaf); - assertEquals("c", leaf.id); - assertSame(parent, leaf.prev); - } -} |