diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java index aec0b5f964..f40824408d 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java @@ -422,7 +422,7 @@ public ValueInstantiator _valueInstantiatorInstance(DeserializationConfig config boolean useProps = _checkIfCreatorPropertyBased(intr, ctor, argDef); if (useProps) { - CreatorProperty[] properties = new CreatorProperty[1]; + SettableBeanProperty[] properties = new SettableBeanProperty[1]; PropertyName name = (argDef == null) ? null : argDef.getFullName(); AnnotatedParameter arg = ctor.getParameter(0); properties[0] = constructCreatorProperty(ctxt, beanDesc, name, 0, arg, @@ -447,7 +447,7 @@ public ValueInstantiator _valueInstantiatorInstance(DeserializationConfig config // do, with some constraints. But that will require bit post processing... AnnotatedParameter nonAnnotatedParam = null; - CreatorProperty[] properties = new CreatorProperty[argCount]; + SettableBeanProperty[] properties = new SettableBeanProperty[argCount]; int explicitNameCount = 0; int implicitWithCreatorCount = 0; int injectCount = 0; diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/SettableBeanProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/SettableBeanProperty.java index f9eb36da07..354675584e 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/SettableBeanProperty.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/SettableBeanProperty.java @@ -435,10 +435,11 @@ public boolean visibleInView(Class activeView) { /** * Method for accessing index of the creator property: for other * types of properties will simply return -1. + * 20.06.2015 bojanv55 - had a problem when returning -1 when deser. ref. object * * @since 2.1 */ - public int getCreatorIndex() { return -1; } + public int getCreatorIndex() { return _propertyIndex; } /** * Accessor for id of injectable value, if this bean property supports diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java index 618818126b..23575f4fbe 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java @@ -9,6 +9,7 @@ import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.deser.CreatorProperty; +import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.deser.ValueInstantiator; import com.fasterxml.jackson.databind.deser.std.StdValueInstantiator; import com.fasterxml.jackson.databind.introspect.*; @@ -60,9 +61,9 @@ public class CreatorCollector protected boolean _hasNonDefaultCreator = false; // when there are injectable values along with delegate: - protected CreatorProperty[] _delegateArgs; + protected SettableBeanProperty[] _delegateArgs; - protected CreatorProperty[] _propertyBasedArgs; + protected SettableBeanProperty[] _propertyBasedArgs; protected AnnotatedParameter _incompleteParameter; @@ -171,14 +172,14 @@ public void addBooleanCreator(AnnotatedWithParams creator, boolean explicit) { } public void addDelegatingCreator(AnnotatedWithParams creator, boolean explicit, - CreatorProperty[] injectables) + SettableBeanProperty[] injectables) { verifyNonDup(creator, C_DELEGATE, explicit); _delegateArgs = injectables; } public void addPropertyCreator(AnnotatedWithParams creator, boolean explicit, - CreatorProperty[] properties) + SettableBeanProperty[] properties) { verifyNonDup(creator, C_PROPS, explicit); // [JACKSON-470] Better ensure we have no duplicate names either... diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java index 3d146e271a..d6c983f7f9 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java @@ -1,6 +1,7 @@ package com.fasterxml.jackson.databind.deser.impl; import java.io.IOException; +import java.lang.reflect.Field; import java.util.BitSet; import com.fasterxml.jackson.core.JsonParser; @@ -182,8 +183,28 @@ public boolean readIdProperty(String propName) throws IOException public Object handleIdValue(final DeserializationContext ctxt, Object bean) throws IOException { if (_objectIdReader != null) { + + //bojanv55 20.06.2015 had problem when deserializing ref. object. + if(_idValue == null){ + //read the value of id from object that needs to be reconstructed + try { + Field f = bean.getClass().getDeclaredField(_objectIdReader.propertyName.getSimpleName()); + f.setAccessible(true); + _idValue = f.get(bean); + f.setAccessible(false); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + if (_idValue != null) { ReadableObjectId roid = ctxt.findObjectId(_idValue, _objectIdReader.generator, _objectIdReader.resolver); + Object res = roid.resolve(); + if(res != null) { + bean = res; + } roid.bindItem(bean); // also: may need to set a property value as well SettableBeanProperty idProp = _objectIdReader.idProperty; diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdValueInstantiator.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdValueInstantiator.java index 439c2561e2..090dbd2b3e 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdValueInstantiator.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdValueInstantiator.java @@ -37,13 +37,13 @@ public class StdValueInstantiator // // // With-args (property-based) construction protected AnnotatedWithParams _withArgsCreator; - protected CreatorProperty[] _constructorArguments; + protected SettableBeanProperty[] _constructorArguments; // // // Delegate construction protected JavaType _delegateType; protected AnnotatedWithParams _delegateCreator; - protected CreatorProperty[] _delegateArguments; + protected SettableBeanProperty[] _delegateArguments; // // // Scalar construction @@ -100,8 +100,8 @@ protected StdValueInstantiator(StdValueInstantiator src) * three), and clear other properties */ public void configureFromObjectSettings(AnnotatedWithParams defaultCreator, - AnnotatedWithParams delegateCreator, JavaType delegateType, CreatorProperty[] delegateArgs, - AnnotatedWithParams withArgsCreator, CreatorProperty[] constructorArgs) + AnnotatedWithParams delegateCreator, JavaType delegateType, SettableBeanProperty[] delegateArgs, + AnnotatedWithParams withArgsCreator, SettableBeanProperty[] constructorArgs) { _defaultCreator = defaultCreator; _delegateCreator = delegateCreator; @@ -247,7 +247,7 @@ public Object createUsingDelegate(DeserializationContext ctxt, Object delegate) final int len = _delegateArguments.length; Object[] args = new Object[len]; for (int i = 0; i < len; ++i) { - CreatorProperty prop = _delegateArguments[i]; + SettableBeanProperty prop = _delegateArguments[i]; if (prop == null) { // delegate args[i] = delegate; } else { // nope, injectable: diff --git a/src/test/java/com/fasterxml/jackson/failing/TestObjectIdReference.java b/src/test/java/com/fasterxml/jackson/failing/TestObjectIdReference.java new file mode 100644 index 0000000000..ffab631440 --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/failing/TestObjectIdReference.java @@ -0,0 +1,201 @@ +package com.fasterxml.jackson.failing; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.BaseMapTest; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class TestObjectIdReference extends BaseMapTest { + + static class Player { + + private int id; + private String name; + private List translations = new ArrayList(); + + public Player(int id, String name) { + this.id = id; + this.name = name; + } + + public Player(){} + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public void addTranslation(Translation translation) { + this.translations.add(translation); + } + + + } + + @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id") + static class Translation { + + private Lang languageId; + private String translation; + + public Translation(String translation, Lang languageId){ + this.translation = translation; + this.languageId = languageId; + } + + public Translation(){} + + public Lang getLanguageId() { + return languageId; + } + + public String getTranslation() { + return translation; + } + + } + + static interface Lang{} + + static class LanguageOk implements Lang{ + + private int value; + + private String kod; + + public LanguageOk(int value, String kod){ + this.value = value; + this.kod = kod; + } + + public LanguageOk(){} + + public int getValue(){ + return this.value; + } + + public String getKod(){ + return this.kod; + } + + } + + @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="value") + static class LanguageId implements Lang { + + private Key value; + + private String kod; + + public LanguageId(Key value, String kod){ + this.value = value; + this.kod = kod; + } + + public LanguageId(){} + + public Key getValue(){ + return this.value; + } + + public String getKod(){ + return this.kod; + } + + } + + static class Key { + + public int val; + + public Key(int val){ + this.val = val; + } + + public Key(){} + + public int getVal(){ + return this.val; + } + + } + + + private final ObjectMapper mapper = new ObjectMapper(); + + public void testDeserializationOfReferenceOK() throws IOException { + + Player player = new Player(1, "Dino"); + + LanguageOk languageId = new LanguageOk(55, "kod"); + + Translation commonTranslation = new Translation("DinoT1", languageId); + Translation commonTranslation2 = new Translation("DinoT2", languageId); + + player.addTranslation(commonTranslation); + player.addTranslation(commonTranslation); + player.addTranslation(commonTranslation2); + + Player player2 = new Player(2, "Bojan"); + player2.addTranslation(commonTranslation); + player2.addTranslation(commonTranslation2); + + mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE); + mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); + + String serialized = mapper.writeValueAsString(player); + String serialized2 = mapper.writeValueAsString(player2); + + //System.out.println(serialized); + //System.out.println(serialized2); + + + Player p1 = mapper.readValue(serialized, Player.class); + Player p2 = mapper.readValue(serialized2, Player.class); + } + + + public void testDeserializationOfReference() throws IOException { + + Player player = new Player(1, "Dino"); + + LanguageId languageId = new LanguageId(new Key(44), "kod"); + + Translation commonTranslation = new Translation("DinoT1", languageId); + Translation commonTranslation2 = new Translation("DinoT2", languageId); + + player.addTranslation(commonTranslation); + player.addTranslation(commonTranslation); + player.addTranslation(commonTranslation2); + + Player player2 = new Player(2, "Bojan"); + player2.addTranslation(commonTranslation); + player2.addTranslation(commonTranslation2); + + mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE); + mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); + + String serialized = mapper.writeValueAsString(player); + String serialized2 = mapper.writeValueAsString(player2); + + System.out.println(serialized); + System.out.println(serialized2); + + Player p1 = mapper.readValue(serialized, Player.class); + Player p2 = mapper.readValue(serialized2, Player.class); + + } + +}