Skip to content

Commit

Permalink
Fix FasterXML#2541 (support merge polymorphic property)
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesWang committed Jan 14, 2022
1 parent abc6669 commit 713062f
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -561,12 +561,16 @@ public final Object deserializeWith(JsonParser p, DeserializationContext ctxt,
}
return _nullProvider.getNullValue(ctxt);
}
// 20-Oct-2016, tatu: Also tricky -- for now, report an error
if (_valueTypeDeserializer != null) {
ctxt.reportBadDefinition(getType(),
String.format("Cannot merge polymorphic property '%s'",
getName()));
// return _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer);
// 25-Oct-2021 Added by James to support merging polymorphic property
// https://github.com/FasterXML/jackson-databind/issues/2541
// Please note we only support merging same type polymorphic property for now,
// merging different type is hard and usually doesn't make sense.
// Please note you need to configure {@link DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES} as false to
// enable this feature otherwise the unknown property exception will be thrown.
JavaType subType = ctxt.getTypeFactory().constructType(toUpdate.getClass());
JsonDeserializer<Object> subTypeValueDeserializer = ctxt.findContextualValueDeserializer(subType, this);
return subTypeValueDeserializer.deserialize(p, ctxt, toUpdate);
}
// 04-May-2018, tatu: [databind#2023] Coercion from String (mostly) can give null
Object value = _valueDeserializer.deserialize(p, ctxt, toUpdate);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.fasterxml.jackson.databind.deser;

import com.fasterxml.jackson.annotation.JsonMerge;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.BaseMapTest;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

public class MergePolymorphicTest extends BaseMapTest {

static class Root {
@JsonMerge
public Child child;
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@JsonSubTypes({
@JsonSubTypes.Type(value = ChildA.class, name = "ChildA"),
@JsonSubTypes.Type(value = ChildB.class, name = "ChildB")
})
static abstract class Child {
}

static class ChildA extends Child {
public String name;
}

static class ChildB extends Child {
public String code;
}

public void testPolymorphicNewObject() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Root root = mapper.readValue("{\"child\": { \"@type\": \"ChildA\", \"name\": \"I'm child A\" }}", Root.class);
assertTrue(root.child instanceof ChildA);
assertEquals("I'm child A", ((ChildA) root.child).name);
}

public void testPolymorphicPropertyCanBeMerged() throws JsonProcessingException {
Root root = new Root();
ChildA childA = new ChildA();
childA.name = "I'm child A";
root.child = childA;
ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.readerForUpdating(root).readValue("{\"child\": { \"@type\": \"ChildA\", \"name\": \"I'm the new name\" }}");
assertTrue(root.child instanceof ChildA);
assertEquals("I'm the new name", ((ChildA) root.child).name);
}

public void testPolymorphicPropertyTypeCanNotBeChanged() throws JsonProcessingException {
Root root = new Root();
ChildA childA = new ChildA();
childA.name = "I'm child A";
root.child = childA;
ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.readerForUpdating(root).readValue("{\"child\": { \"@type\": \"ChildB\", \"code\": \"I'm the code\" }}");
// The polymorphic type can't be changed
assertTrue(root.child instanceof ChildA);
assertEquals("I'm child A", ((ChildA) root.child).name);
}

}

0 comments on commit 713062f

Please sign in to comment.