-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
android-record: Support deserializing polymorphic members of records (f…
…ixes #248).
- Loading branch information
Showing
3 changed files
with
132 additions
and
2 deletions.
There are no files selected for viewing
52 changes: 52 additions & 0 deletions
52
...d/src/main/java/com/fasterxml/jackson/module/androidrecord/AndroidRecordInstantiator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package com.fasterxml.jackson.module.androidrecord; | ||
|
||
import com.fasterxml.jackson.databind.BeanDescription; | ||
import com.fasterxml.jackson.databind.DeserializationContext; | ||
import com.fasterxml.jackson.databind.JsonMappingException; | ||
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.AnnotatedParameter; | ||
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; | ||
|
||
public class AndroidRecordInstantiator extends StdValueInstantiator { | ||
protected AndroidRecordInstantiator(StdValueInstantiator src) { | ||
super(src); | ||
} | ||
|
||
public ValueInstantiator createContextual(DeserializationContext ctxt, BeanDescription beanDesc) throws JsonMappingException { | ||
boolean wasChanged = false; | ||
SettableBeanProperty[] newCtorArgs = new SettableBeanProperty[_constructorArguments.length]; | ||
for (int i = 0; i < _constructorArguments.length; i++) { | ||
SettableBeanProperty prop = _constructorArguments[i]; | ||
if (!prop.hasValueTypeDeserializer()) { | ||
TypeDeserializer typeDeserializer = ctxt.getFactory().findTypeDeserializer(ctxt.getConfig(), prop.getType()); | ||
if (typeDeserializer != null) { | ||
prop = CreatorProperty.construct( | ||
prop.getFullName(), | ||
prop.getType(), | ||
prop.getWrapperName(), | ||
typeDeserializer, | ||
prop.getMember().getAllAnnotations(), | ||
(AnnotatedParameter) prop.getMember(), | ||
prop.getCreatorIndex(), | ||
ctxt.getAnnotationIntrospector().findInjectableValue(prop.getMember()), | ||
prop.getMetadata() | ||
); | ||
wasChanged = true; | ||
} | ||
} | ||
newCtorArgs[i] = prop; | ||
} | ||
|
||
|
||
if (wasChanged) { | ||
AndroidRecordInstantiator newInstantiator = new AndroidRecordInstantiator(this); | ||
newInstantiator._constructorArguments = newCtorArgs; | ||
return newInstantiator; | ||
} else { | ||
return this; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
...rd/src/test/java/com/fasterxml/jackson/module/androidrecord/AbstractRecordMemberTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package com.fasterxml.jackson.module.androidrecord; | ||
|
||
import com.android.tools.r8.RecordTag; | ||
import com.fasterxml.jackson.annotation.JsonCreator; | ||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.fasterxml.jackson.annotation.JsonSubTypes; | ||
import com.fasterxml.jackson.annotation.JsonTypeInfo; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
|
||
public class AbstractRecordMemberTest extends BaseMapTest { | ||
|
||
static final class RootRecord extends RecordTag { | ||
|
||
private final AbstractMember member; | ||
|
||
public RootRecord(AbstractMember member) { | ||
this.member = member; | ||
} | ||
|
||
public AbstractMember member() { | ||
return member; | ||
} | ||
} | ||
|
||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@class") | ||
@JsonSubTypes({ | ||
@JsonSubTypes.Type(value = StringMember.class, name = "string"), | ||
@JsonSubTypes.Type(value = IntMember.class, name = "int") | ||
}) | ||
static abstract class AbstractMember { | ||
} | ||
|
||
static final class StringMember extends AbstractMember { | ||
|
||
private final String val; | ||
|
||
@JsonCreator | ||
public StringMember(@JsonProperty("val") String val) { | ||
this.val = val; | ||
} | ||
|
||
public String getVal() { | ||
return val; | ||
} | ||
} | ||
|
||
static final class IntMember extends AbstractMember { | ||
|
||
private final int val; | ||
|
||
@JsonCreator | ||
public IntMember(@JsonProperty("val") int val) { | ||
this.val = val; | ||
} | ||
|
||
public int getVal() { | ||
return val; | ||
} | ||
} | ||
|
||
private final ObjectMapper MAPPER = newJsonMapper(); | ||
|
||
/* | ||
/********************************************************************** | ||
/* https://github.com/FasterXML/jackson-modules-base/issues/248 | ||
/********************************************************************** | ||
*/ | ||
public void testDeserializeRecordWithAbstractMember() throws Exception { | ||
RootRecord value = MAPPER.readValue("{\"member\":{\"@class\":\"string\",\"val\":\"Hello, abstract member!\"}}", | ||
RootRecord.class); | ||
assertNotNull(value.member()); | ||
assertEquals(StringMember.class, value.member().getClass()); | ||
assertEquals("Hello, abstract member!", ((StringMember)value.member()).getVal()); | ||
} | ||
} |