22
22
// for [databind#43], deduction-based polymorphism
23
23
public class TestPolymorphicDeduction extends BaseMapTest {
24
24
25
+ @ JsonTypeInfo (use = DEDUCTION )
26
+ @ JsonSubTypes ( {@ Type (LiveCat .class ), @ Type (DeadCat .class ), @ Type (Fleabag .class )})
27
+ // A general supertype with no properties - used for tests involving {}
28
+ interface Feline {}
29
+
25
30
@ JsonTypeInfo (use = DEDUCTION )
26
31
@ JsonSubTypes ( {@ Type (LiveCat .class ), @ Type (DeadCat .class )})
27
- public static class Cat {
32
+ // A supertype containing common properties
33
+ public static class Cat implements Feline {
28
34
public String name ;
29
35
}
30
36
37
+ // Distinguished by its parent and a unique property
31
38
static class DeadCat extends Cat {
32
39
public String causeOfDeath ;
33
40
}
34
41
42
+ // Distinguished by its parent and a unique property
35
43
static class LiveCat extends Cat {
36
44
public boolean angry ;
37
45
}
38
46
47
+ // No distinguishing properties whatsoever
48
+ static class Fleabag implements Feline {
49
+ // NO OP
50
+ }
51
+
52
+ // Something to put felines in
39
53
static class Box {
40
- public Cat cat ;
54
+ public Feline feline ;
41
55
}
42
56
43
57
/*
@@ -50,8 +64,12 @@ static class Box {
50
64
private static final String liveCatJson = aposToQuotes ("{'name':'Felix','angry':true}" );
51
65
private static final String luckyCatJson = aposToQuotes ("{'name':'Felix','angry':true,'lives':8}" );
52
66
private static final String ambiguousCatJson = aposToQuotes ("{'name':'Felix','age':2}" );
53
- private static final String box1Json = aposToQuotes ("{'cat':" + liveCatJson + "}" );
54
- private static final String box2Json = aposToQuotes ("{'cat':" + deadCatJson + "}" );
67
+ private static final String fleabagJson = aposToQuotes ("{}" );
68
+ private static final String box1Json = aposToQuotes ("{'feline':" + liveCatJson + "}" );
69
+ private static final String box2Json = aposToQuotes ("{'feline':" + deadCatJson + "}" );
70
+ private static final String box3Json = aposToQuotes ("{'feline':" + fleabagJson + "}" );
71
+ private static final String box4Json = aposToQuotes ("{'feline':null}" );
72
+ private static final String box5Json = aposToQuotes ("{}" );
55
73
private static final String arrayOfCatsJson = aposToQuotes ("[" + liveCatJson + "," + deadCatJson + "]" );
56
74
private static final String mapOfCatsJson = aposToQuotes ("{'live':" + liveCatJson + "}" );
57
75
@@ -75,6 +93,24 @@ public void testSimpleInference() throws Exception {
75
93
assertEquals ("entropy" , ((DeadCat )cat ).causeOfDeath );
76
94
}
77
95
96
+ public void testSimpleInferenceOfEmptySubtype () throws Exception {
97
+ // Given:
98
+ ObjectMapper mapper = sharedMapper ();
99
+ // When:
100
+ Feline feline = mapper .readValue (fleabagJson , Feline .class );
101
+ // Then:
102
+ assertTrue (feline instanceof Fleabag );
103
+ }
104
+
105
+ public void testSimpleInferenceOfEmptySubtypeDoesntMatchNull () throws Exception {
106
+ // Given:
107
+ ObjectMapper mapper = sharedMapper ();
108
+ // When:
109
+ Feline feline = mapper .readValue ("null" , Feline .class );
110
+ // Then:
111
+ assertNull (feline );
112
+ }
113
+
78
114
public void testCaseInsensitiveInference () throws Exception {
79
115
Cat cat = JsonMapper .builder () // Don't use shared mapper!
80
116
.configure (MapperFeature .ACCEPT_CASE_INSENSITIVE_PROPERTIES , true )
@@ -101,16 +137,27 @@ public void testCaseInsensitiveInference() throws Exception {
101
137
102
138
public void testContainedInference () throws Exception {
103
139
Box box = sharedMapper ().readValue (box1Json , Box .class );
104
- assertTrue (box .cat instanceof LiveCat );
105
- assertSame (box .cat .getClass (), LiveCat .class );
106
- assertEquals ("Felix" , box .cat .name );
107
- assertTrue (((LiveCat )box .cat ).angry );
140
+ assertTrue (box .feline instanceof LiveCat );
141
+ assertSame (box .feline .getClass (), LiveCat .class );
142
+ assertEquals ("Felix" , (( LiveCat ) box .feline ) .name );
143
+ assertTrue (((LiveCat )box .feline ).angry );
108
144
109
145
box = sharedMapper ().readValue (box2Json , Box .class );
110
- assertTrue (box .cat instanceof DeadCat );
111
- assertSame (box .cat .getClass (), DeadCat .class );
112
- assertEquals ("Felix" , box .cat .name );
113
- assertEquals ("entropy" , ((DeadCat )box .cat ).causeOfDeath );
146
+ assertTrue (box .feline instanceof DeadCat );
147
+ assertSame (box .feline .getClass (), DeadCat .class );
148
+ assertEquals ("Felix" , ((DeadCat )box .feline ).name );
149
+ assertEquals ("entropy" , ((DeadCat )box .feline ).causeOfDeath );
150
+ }
151
+
152
+ public void testContainedInferenceOfEmptySubtype () throws Exception {
153
+ Box box = sharedMapper ().readValue (box3Json , Box .class );
154
+ assertTrue (box .feline instanceof Fleabag );
155
+
156
+ box = sharedMapper ().readValue (box4Json , Box .class );
157
+ assertNull ("null != {}" , box .feline );
158
+
159
+ box = sharedMapper ().readValue (box5Json , Box .class );
160
+ assertNull ("<absent> != {}" , box .feline );
114
161
}
115
162
116
163
public void testListInference () throws Exception {
0 commit comments