BAEL-5115 Deduction-Based Polymorphism in Jackson 2.12 (#11732)
* BAEL-5115 Deduction-Based Polymorphism in Jackson 2.12 * Fix pmd * Code review changes * Improvements * Code review * Code review * fix typo * Rename package * Apply formatter * Add old deduction * revert
This commit is contained in:
parent
2d672af774
commit
de77319b35
|
@ -0,0 +1,12 @@
|
|||
package com.baeldung.jackson.deductionbasedpolymorphism;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
|
||||
|
||||
@JsonTypeInfo(use = Id.DEDUCTION)
|
||||
@JsonSubTypes({ @Type(ImperialSpy.class), @Type(King.class), @Type(Knight.class) })
|
||||
public interface Character {
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.baeldung.jackson.deductionbasedpolymorphism;
|
||||
|
||||
public class ControlledCharacter {
|
||||
|
||||
private Character character;
|
||||
|
||||
public Character getCharacter() {
|
||||
return character;
|
||||
}
|
||||
|
||||
public void setCharacter(Character character) {
|
||||
this.character = character;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.baeldung.jackson.deductionbasedpolymorphism;
|
||||
|
||||
public class ImperialSpy implements Character {
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.baeldung.jackson.deductionbasedpolymorphism;
|
||||
|
||||
public class King extends NamedCharacter {
|
||||
|
||||
private String land;
|
||||
|
||||
public String getLand() {
|
||||
return land;
|
||||
}
|
||||
|
||||
public void setLand(String land) {
|
||||
this.land = land;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.baeldung.jackson.deductionbasedpolymorphism;
|
||||
|
||||
public class Knight extends NamedCharacter {
|
||||
|
||||
private String weapon;
|
||||
|
||||
public String getWeapon() {
|
||||
return weapon;
|
||||
}
|
||||
|
||||
public void setWeapon(String weapon) {
|
||||
this.weapon = weapon;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.baeldung.jackson.deductionbasedpolymorphism;
|
||||
|
||||
public class NamedCharacter implements Character {
|
||||
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.baeldung.jackson.deductionbasedpolymorphism;
|
||||
|
||||
import static com.baeldung.jackson.deductionbasedpolymorphism.JsonStringFormatterUtil.formatJson;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
|
||||
class CaseInsensitiveInferenceUnitTest {
|
||||
|
||||
private final ObjectMapper objectMapper = JsonMapper.builder()
|
||||
.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true)
|
||||
.build();
|
||||
|
||||
@Test
|
||||
void givenACaseInsensitiveKnight_whenMapping_thenExpectKnight() throws Exception {
|
||||
String knightJson = formatJson("{'NaMe':'Ostrava, of Boletaria', 'WeaPON':'Rune Sword'}");
|
||||
|
||||
Character character = objectMapper.readValue(knightJson, Character.class);
|
||||
|
||||
assertTrue(character instanceof Knight);
|
||||
assertSame(character.getClass(), Knight.class);
|
||||
Knight knight = (Knight) character;
|
||||
assertEquals("Ostrava, of Boletaria", knight.getName());
|
||||
assertEquals("Rune Sword", knight.getWeapon());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package com.baeldung.jackson.deductionbasedpolymorphism;
|
||||
|
||||
import static com.baeldung.jackson.deductionbasedpolymorphism.JsonStringFormatterUtil.formatJson;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
|
||||
class ContainedInferenceUnitTest {
|
||||
|
||||
private final ObjectMapper objectMapper = JsonMapper.builder()
|
||||
.build();
|
||||
|
||||
@Test
|
||||
void givenAKnightControlledCharacter_whenMapping_thenExpectAControlledCharacterWithKnight() throws Exception {
|
||||
String controlledCharacterJson = formatJson("{'character': {'name': 'Ostrava, of Boletaria', 'weapon': 'Rune Sword'}}");
|
||||
|
||||
ControlledCharacter controlledCharacter = objectMapper.readValue(controlledCharacterJson, ControlledCharacter.class);
|
||||
Character character = controlledCharacter.getCharacter();
|
||||
|
||||
assertTrue(character instanceof Knight);
|
||||
assertSame(character.getClass(), Knight.class);
|
||||
Knight knight = (Knight) character;
|
||||
assertEquals("Ostrava, of Boletaria", knight.getName());
|
||||
assertEquals("Rune Sword", knight.getWeapon());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenAKingControlledCharacter_whenMapping_thenExpectAControlledCharacterWithKing() throws Exception {
|
||||
String controlledCharacterJson = formatJson("{'character': {'name': 'King Allant', 'land': 'Boletaria'}}");
|
||||
|
||||
ControlledCharacter controlledCharacter = objectMapper.readValue(controlledCharacterJson, ControlledCharacter.class);
|
||||
Character character = controlledCharacter.getCharacter();
|
||||
|
||||
assertTrue(character instanceof King);
|
||||
assertSame(character.getClass(), King.class);
|
||||
King king = (King) character;
|
||||
assertEquals("King Allant", king.getName());
|
||||
assertEquals("Boletaria", king.getLand());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenAnEmptySubtype_whenMapping_thenExpectImperialSpy() throws Exception {
|
||||
String controlledCharacterJson = formatJson("{'character': {}}");
|
||||
|
||||
ControlledCharacter controlledCharacter = objectMapper.readValue(controlledCharacterJson, ControlledCharacter.class);
|
||||
|
||||
assertTrue(controlledCharacter.getCharacter() instanceof ImperialSpy);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenANullCharacter_whenMapping_thenExpectNullCharacter() throws Exception {
|
||||
String controlledCharacterJson = formatJson("{'character': null}");
|
||||
|
||||
ControlledCharacter controlledCharacter = objectMapper.readValue(controlledCharacterJson, ControlledCharacter.class);
|
||||
|
||||
assertNull(controlledCharacter.getCharacter());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenAAnAbsentCharacter_whenMapping_thenExpectNullCharacter() throws Exception {
|
||||
String controlledCharacterJson = formatJson("{}");
|
||||
|
||||
ControlledCharacter controlledCharacter = objectMapper.readValue(controlledCharacterJson, ControlledCharacter.class);
|
||||
|
||||
assertNull(controlledCharacter.getCharacter());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.baeldung.jackson.deductionbasedpolymorphism;
|
||||
|
||||
public class JsonStringFormatterUtil {
|
||||
|
||||
public static String formatJson(String input) {
|
||||
return input.replaceAll("'", "\"");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package com.baeldung.jackson.deductionbasedpolymorphism;
|
||||
|
||||
import static com.baeldung.jackson.deductionbasedpolymorphism.JsonStringFormatterUtil.formatJson;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
|
||||
class SimpleInferenceUnitTest {
|
||||
|
||||
private final ObjectMapper objectMapper = JsonMapper.builder()
|
||||
.build();
|
||||
|
||||
@Test
|
||||
void givenAKnight_whenMapping_thenExpectAKnightType() throws Exception {
|
||||
String knightJson = formatJson("{'name':'Ostrava, of Boletaria', 'weapon':'Rune Sword'}");
|
||||
|
||||
Character character = objectMapper.readValue(knightJson, Character.class);
|
||||
|
||||
assertTrue(character instanceof Knight);
|
||||
assertSame(character.getClass(), Knight.class);
|
||||
Knight king = (Knight) character;
|
||||
assertEquals("Ostrava, of Boletaria", king.getName());
|
||||
assertEquals("Rune Sword", king.getWeapon());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenAKing_whenMapping_thenExpectAKingType() throws Exception {
|
||||
String kingJson = formatJson("{'name':'Old King Allant', 'land':'Boletaria'}");
|
||||
|
||||
Character character = objectMapper.readValue(kingJson, Character.class);
|
||||
|
||||
assertTrue(character instanceof King);
|
||||
assertSame(character.getClass(), King.class);
|
||||
King king = (King) character;
|
||||
assertEquals("Old King Allant", king.getName());
|
||||
assertEquals("Boletaria", king.getLand());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenAnEmptyObject_whenMapping_thenExpectAnImperialSpy() throws Exception {
|
||||
String imperialSpyJson = "{}";
|
||||
|
||||
Character character = objectMapper.readValue(imperialSpyJson, Character.class);
|
||||
|
||||
assertTrue(character instanceof ImperialSpy);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenANullObject_whenMapping_thenExpectANullObject() throws Exception {
|
||||
Character character = objectMapper.readValue("null", Character.class);
|
||||
|
||||
assertNull(character);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue