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