• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.jsontype;
2 
3 import java.io.IOException;
4 import java.util.LinkedHashMap;
5 import java.util.Map;
6 
7 import com.fasterxml.jackson.annotation.*;
8 import com.fasterxml.jackson.core.JsonGenerator;
9 import com.fasterxml.jackson.databind.*;
10 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
11 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
12 import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
13 
14 public class TypeRefinementForMapTest extends BaseMapTest
15 {
16     interface HasUniqueId<K> {
getId()17         K getId();
18     }
19 
20     static class Item implements HasUniqueId<String>
21     {
22         public String id;
23         public String property;
24 
25         @Override
getId()26         public String getId() { return id; }
27     }
28 
29     static class Data
30     {
31         public String id;
32 
33         @JsonDeserialize(as = MyHashMap.class)
34         public Map<String, Item> items;
35 
36         // Would work with straight arguments:
37 //        public MyHashMap<String, Item> items;
38     }
39 
40     @SuppressWarnings("serial")
41     static class MyHashMap<K, V extends HasUniqueId<K>>
42         extends LinkedHashMap<K, V>
43     {
44         @JsonCreator(mode=JsonCreator.Mode.DELEGATING)
MyHashMap(V[] values)45         public MyHashMap(V[] values) {
46             for (int i = 0; i < values.length; i++) {
47                 V v = values[i];
48                 put(v.getId(), v);
49             }
50         }
51     }
52 
53     // for [databind#1384]
54     @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
55     public static final class TestClass {
56         @JsonProperty("mapProperty")
57         @JsonSerialize(keyUsing = CompoundKeySerializer.class)
58         @JsonDeserialize(keyUsing = CompoundKeyDeserializer.class)
59         private final Map<CompoundKey, String> mapProperty;
60 
61         @JsonCreator
TestClass(@sonProperty"mapProperty") Map<CompoundKey, String> mapProperty)62         private TestClass(@JsonProperty("mapProperty") Map<CompoundKey, String> mapProperty) {
63             this.mapProperty = mapProperty;
64         }
65     }
66 
67     static final class CompoundKey {
68         private String part0;
69         private String part1;
70 
CompoundKey(String part0, String part1)71         public CompoundKey(String part0, String part1) {
72             this.part0 = part0;
73             this.part1 = part1;
74         }
75 
getPart0()76         public String getPart0() { return part0; }
getPart1()77         public String getPart1() { return part1; }
78     }
79 
80     static class CompoundKeyDeserializer extends KeyDeserializer {
81         @Override
deserializeKey(String s, DeserializationContext deserializationContext)82         public Object deserializeKey(String s, DeserializationContext deserializationContext) {
83             String[] parts = s.split("\\|");
84             return new CompoundKey(parts[0], parts[1]);
85         }
86     }
87 
88     static class CompoundKeySerializer extends JsonSerializer<CompoundKey> {
89         @Override
serialize(CompoundKey compoundKey, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)90         public void serialize(CompoundKey compoundKey, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
91             jsonGenerator.writeFieldName(compoundKey.getPart0() + '|' + compoundKey.getPart1());
92         }
93     }
94 
95     /*
96     /*******************************************************
97     /* Test methods
98     /*******************************************************
99      */
100 
testMapRefinement()101     public void testMapRefinement() throws Exception
102     {
103         String ID1 = "3a6383d4-8123-4c43-8b8d-7cedf3e59404";
104         String ID2 = "81c3d978-90c4-4b00-8da1-1c39ffcab02c";
105         String json = aposToQuotes(
106 "{'id':'"+ID1+"','items':[{'id':'"+ID2+"','property':'value'}]}");
107 
108         ObjectMapper m = new ObjectMapper();
109         Data data = m.readValue(json, Data.class);
110 
111         assertEquals(ID1, data.id);
112         assertNotNull(data.items);
113         assertEquals(1, data.items.size());
114         Item value = data.items.get(ID2);
115         assertNotNull(value);
116         assertEquals("value", value.property);
117     }
118 
119     // for [databind#1384]
testMapKeyRefinement1384()120     public void testMapKeyRefinement1384() throws Exception
121     {
122         final String TEST_INSTANCE_SERIALIZED =
123                 "{\"mapProperty\":[\"java.util.HashMap\",{\"Compound|Key\":\"Value\"}]}";
124         ObjectMapper mapper = jsonMapperBuilder()
125                 .activateDefaultTyping(NoCheckSubTypeValidator.instance,
126                         ObjectMapper.DefaultTyping.NON_FINAL)
127                 .build();
128 
129         TestClass testInstance = mapper.readValue(TEST_INSTANCE_SERIALIZED, TestClass.class);
130         assertEquals(1, testInstance.mapProperty.size());
131         Object key = testInstance.mapProperty.keySet().iterator().next();
132         assertEquals(CompoundKey.class, key.getClass());
133         String testInstanceSerialized = mapper.writeValueAsString(testInstance);
134         assertEquals(TEST_INSTANCE_SERIALIZED, testInstanceSerialized);
135     }
136 }
137