• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind;
2 
3 import java.io.IOException;
4 import java.util.*;
5 
6 import com.fasterxml.jackson.annotation.*;
7 import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
8 import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
9 import com.fasterxml.jackson.core.*;
10 import com.fasterxml.jackson.databind.DeserializationContext;
11 import com.fasterxml.jackson.databind.JsonDeserializer;
12 import com.fasterxml.jackson.databind.JsonSerializer;
13 import com.fasterxml.jackson.databind.KeyDeserializer;
14 import com.fasterxml.jackson.databind.ObjectMapper;
15 import com.fasterxml.jackson.databind.SerializerProvider;
16 import com.fasterxml.jackson.databind.annotation.*;
17 import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
18 import com.fasterxml.jackson.databind.cfg.MapperConfig;
19 import com.fasterxml.jackson.databind.introspect.Annotated;
20 import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
21 import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
22 import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase;
23 import com.fasterxml.jackson.databind.type.TypeFactory;
24 
25 public class TestHandlerInstantiation extends BaseMapTest
26 {
27     /*
28     /**********************************************************************
29     /* Helper classes, beans
30     /**********************************************************************
31      */
32 
33     @JsonDeserialize(using=MyBeanDeserializer.class)
34     @JsonSerialize(using=MyBeanSerializer.class)
35     static class MyBean
36     {
37         public String value;
38 
MyBean()39         public MyBean() { this(null); }
MyBean(String s)40         public MyBean(String s) { value = s; }
41     }
42 
43     @SuppressWarnings("serial")
44     @JsonDeserialize(keyUsing=MyKeyDeserializer.class)
45     static class MyMap extends HashMap<String,String> { }
46 
47     @JsonTypeInfo(use=Id.CUSTOM, include=As.WRAPPER_ARRAY)
48     @JsonTypeIdResolver(TestCustomIdResolver.class)
49     static class TypeIdBean {
50         public int x;
51 
TypeIdBean()52         public TypeIdBean() { }
TypeIdBean(int x)53         public TypeIdBean(int x) { this.x = x; }
54     }
55 
56     static class TypeIdBeanWrapper {
57         public TypeIdBean bean;
58 
TypeIdBeanWrapper()59         public TypeIdBeanWrapper() { this(null); }
TypeIdBeanWrapper(TypeIdBean b)60         public TypeIdBeanWrapper(TypeIdBean b) { bean = b; }
61     }
62 
63     /*
64     /**********************************************************************
65     /* Helper classes, serializers/deserializers/resolvers
66     /**********************************************************************
67      */
68 
69     static class MyBeanDeserializer extends JsonDeserializer<MyBean>
70     {
71         public String _prefix = "";
72 
MyBeanDeserializer(String p)73         public MyBeanDeserializer(String p) {
74             _prefix  = p;
75         }
76 
77         @Override
deserialize(JsonParser jp, DeserializationContext ctxt)78         public MyBean deserialize(JsonParser jp, DeserializationContext ctxt)
79                 throws IOException, JsonProcessingException
80         {
81             return new MyBean(_prefix+jp.getText());
82         }
83     }
84 
85     static class MyKeyDeserializer extends KeyDeserializer
86     {
MyKeyDeserializer()87         public MyKeyDeserializer() { }
88 
89         @Override
deserializeKey(String key, DeserializationContext ctxt)90         public Object deserializeKey(String key, DeserializationContext ctxt)
91                 throws IOException, JsonProcessingException
92         {
93             return "KEY";
94         }
95     }
96 
97     static class MyBeanSerializer extends JsonSerializer<MyBean>
98     {
99         public String _prefix = "";
100 
MyBeanSerializer(String p)101         public MyBeanSerializer(String p) {
102             _prefix  = p;
103         }
104 
105         @Override
serialize(MyBean value, JsonGenerator jgen, SerializerProvider provider)106         public void serialize(MyBean value, JsonGenerator jgen, SerializerProvider provider)
107             throws IOException, JsonProcessingException
108         {
109             jgen.writeString(_prefix + value.value);
110         }
111     }
112 
113     // copied from "TestCustomTypeIdResolver"
114     static class TestCustomIdResolver extends TypeIdResolverBase
115     {
116         static List<JavaType> initTypes;
117 
118         final String _id;
119 
TestCustomIdResolver(String idForBean)120         public TestCustomIdResolver(String idForBean) {
121             _id = idForBean;
122         }
123 
124         @Override
getMechanism()125         public Id getMechanism() {
126             return Id.CUSTOM;
127         }
128 
129         @Override
idFromValue(Object value)130         public String idFromValue(Object value)
131         {
132             if (value.getClass() == TypeIdBean.class) {
133                 return _id;
134             }
135             return "unknown";
136         }
137 
138         @Override
idFromValueAndType(Object value, Class<?> type)139         public String idFromValueAndType(Object value, Class<?> type) {
140             return idFromValue(value);
141         }
142 
143         @Override
init(JavaType baseType)144         public void init(JavaType baseType) {
145             if (initTypes != null) {
146                 initTypes.add(baseType);
147             }
148         }
149 
150         @Override
typeFromId(DatabindContext context, String id)151         public JavaType typeFromId(DatabindContext context, String id)
152         {
153             if (id.equals(_id)) {
154                 return TypeFactory.defaultInstance().constructType(TypeIdBean.class);
155             }
156             return null;
157         }
158         @Override
idFromBaseType()159         public String idFromBaseType() {
160             return "xxx";
161         }
162     }
163 
164     /*
165     /**********************************************************************
166     /* Helper classes, handler instantiator
167     /**********************************************************************
168      */
169 
170     static class MyInstantiator extends HandlerInstantiator
171     {
172         private final String _prefix;
173 
MyInstantiator(String p)174         public MyInstantiator(String p) {
175             _prefix = p;
176         }
177 
178         @Override
deserializerInstance(DeserializationConfig config, Annotated annotated, Class<?> deserClass)179         public JsonDeserializer<?> deserializerInstance(DeserializationConfig config,
180                 Annotated annotated,
181                 Class<?> deserClass)
182         {
183             if (deserClass == MyBeanDeserializer.class) {
184                 return new MyBeanDeserializer(_prefix);
185             }
186             return null;
187         }
188 
189         @Override
keyDeserializerInstance(DeserializationConfig config, Annotated annotated, Class<?> keyDeserClass)190         public KeyDeserializer keyDeserializerInstance(DeserializationConfig config,
191                 Annotated annotated, Class<?> keyDeserClass)
192         {
193             if (keyDeserClass == MyKeyDeserializer.class) {
194                 return new MyKeyDeserializer();
195             }
196             return null;
197 
198         }
199 
200         @Override
serializerInstance(SerializationConfig config, Annotated annotated, Class<?> serClass)201         public JsonSerializer<?> serializerInstance(SerializationConfig config,
202                 Annotated annotated, Class<?> serClass)
203         {
204             if (serClass == MyBeanSerializer.class) {
205                 return new MyBeanSerializer(_prefix);
206             }
207             return null;
208         }
209 
210         @Override
typeIdResolverInstance(MapperConfig<?> config, Annotated annotated, Class<?> resolverClass)211         public TypeIdResolver typeIdResolverInstance(MapperConfig<?> config,
212                 Annotated annotated, Class<?> resolverClass)
213         {
214             if (resolverClass == TestCustomIdResolver.class) {
215                 return new TestCustomIdResolver("!!!");
216             }
217             return null;
218         }
219 
220         @Override
typeResolverBuilderInstance(MapperConfig<?> config, Annotated annotated, Class<?> builderClass)221         public TypeResolverBuilder<?> typeResolverBuilderInstance(MapperConfig<?> config, Annotated annotated,
222                 Class<?> builderClass)
223         {
224             return null;
225         }
226     }
227 
228     /*
229     /**********************************************************************
230     /* Unit tests
231     /**********************************************************************
232      */
233 
testDeserializer()234     public void testDeserializer() throws Exception
235     {
236         ObjectMapper mapper = new ObjectMapper();
237         mapper.setHandlerInstantiator(new MyInstantiator("abc:"));
238         MyBean result = mapper.readValue(quote("123"), MyBean.class);
239         assertEquals("abc:123", result.value);
240     }
241 
testKeyDeserializer()242     public void testKeyDeserializer() throws Exception
243     {
244         ObjectMapper mapper = new ObjectMapper();
245         mapper.setHandlerInstantiator(new MyInstantiator("abc:"));
246         MyMap map = mapper.readValue("{\"a\":\"b\"}", MyMap.class);
247         // easiest to test by just serializing...
248         assertEquals("{\"KEY\":\"b\"}", mapper.writeValueAsString(map));
249     }
250 
testSerializer()251     public void testSerializer() throws Exception
252     {
253         ObjectMapper mapper = new ObjectMapper();
254         mapper.setHandlerInstantiator(new MyInstantiator("xyz:"));
255         assertEquals(quote("xyz:456"), mapper.writeValueAsString(new MyBean("456")));
256     }
257 
testTypeIdResolver()258     public void testTypeIdResolver() throws Exception
259     {
260         ObjectMapper mapper = new ObjectMapper();
261         mapper.setHandlerInstantiator(new MyInstantiator("foobar"));
262         String json = mapper.writeValueAsString(new TypeIdBeanWrapper(new TypeIdBean(123)));
263         // should now use our custom id scheme:
264         assertEquals("{\"bean\":[\"!!!\",{\"x\":123}]}", json);
265         // and bring it back too:
266         TypeIdBeanWrapper result = mapper.readValue(json, TypeIdBeanWrapper.class);
267         TypeIdBean bean = result.bean;
268         assertEquals(123, bean.x);
269     }
270 
271 }
272