package com.fasterxml.jackson.databind; import java.io.IOException; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.*; import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; import com.fasterxml.jackson.databind.cfg.MapperConfig; import com.fasterxml.jackson.databind.introspect.Annotated; import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase; import com.fasterxml.jackson.databind.type.TypeFactory; public class TestHandlerInstantiation extends BaseMapTest { /* /********************************************************************** /* Helper classes, beans /********************************************************************** */ @JsonDeserialize(using=MyBeanDeserializer.class) @JsonSerialize(using=MyBeanSerializer.class) static class MyBean { public String value; public MyBean() { this(null); } public MyBean(String s) { value = s; } } @SuppressWarnings("serial") @JsonDeserialize(keyUsing=MyKeyDeserializer.class) static class MyMap extends HashMap<String,String> { } @JsonTypeInfo(use=Id.CUSTOM, include=As.WRAPPER_ARRAY) @JsonTypeIdResolver(TestCustomIdResolver.class) static class TypeIdBean { public int x; public TypeIdBean() { } public TypeIdBean(int x) { this.x = x; } } static class TypeIdBeanWrapper { public TypeIdBean bean; public TypeIdBeanWrapper() { this(null); } public TypeIdBeanWrapper(TypeIdBean b) { bean = b; } } /* /********************************************************************** /* Helper classes, serializers/deserializers/resolvers /********************************************************************** */ static class MyBeanDeserializer extends JsonDeserializer<MyBean> { public String _prefix = ""; public MyBeanDeserializer(String p) { _prefix = p; } @Override public MyBean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { return new MyBean(_prefix+jp.getText()); } } static class MyKeyDeserializer extends KeyDeserializer { public MyKeyDeserializer() { } @Override public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException, JsonProcessingException { return "KEY"; } } static class MyBeanSerializer extends JsonSerializer<MyBean> { public String _prefix = ""; public MyBeanSerializer(String p) { _prefix = p; } @Override public void serialize(MyBean value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeString(_prefix + value.value); } } // copied from "TestCustomTypeIdResolver" static class TestCustomIdResolver extends TypeIdResolverBase { static List<JavaType> initTypes; final String _id; public TestCustomIdResolver(String idForBean) { _id = idForBean; } @Override public Id getMechanism() { return Id.CUSTOM; } @Override public String idFromValue(Object value) { if (value.getClass() == TypeIdBean.class) { return _id; } return "unknown"; } @Override public String idFromValueAndType(Object value, Class<?> type) { return idFromValue(value); } @Override public void init(JavaType baseType) { if (initTypes != null) { initTypes.add(baseType); } } @Override public JavaType typeFromId(DatabindContext context, String id) { if (id.equals(_id)) { return TypeFactory.defaultInstance().constructType(TypeIdBean.class); } return null; } @Override public String idFromBaseType() { return "xxx"; } } /* /********************************************************************** /* Helper classes, handler instantiator /********************************************************************** */ static class MyInstantiator extends HandlerInstantiator { private final String _prefix; public MyInstantiator(String p) { _prefix = p; } @Override public JsonDeserializer<?> deserializerInstance(DeserializationConfig config, Annotated annotated, Class<?> deserClass) { if (deserClass == MyBeanDeserializer.class) { return new MyBeanDeserializer(_prefix); } return null; } @Override public KeyDeserializer keyDeserializerInstance(DeserializationConfig config, Annotated annotated, Class<?> keyDeserClass) { if (keyDeserClass == MyKeyDeserializer.class) { return new MyKeyDeserializer(); } return null; } @Override public JsonSerializer<?> serializerInstance(SerializationConfig config, Annotated annotated, Class<?> serClass) { if (serClass == MyBeanSerializer.class) { return new MyBeanSerializer(_prefix); } return null; } @Override public TypeIdResolver typeIdResolverInstance(MapperConfig<?> config, Annotated annotated, Class<?> resolverClass) { if (resolverClass == TestCustomIdResolver.class) { return new TestCustomIdResolver("!!!"); } return null; } @Override public TypeResolverBuilder<?> typeResolverBuilderInstance(MapperConfig<?> config, Annotated annotated, Class<?> builderClass) { return null; } } /* /********************************************************************** /* Unit tests /********************************************************************** */ public void testDeserializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setHandlerInstantiator(new MyInstantiator("abc:")); MyBean result = mapper.readValue(quote("123"), MyBean.class); assertEquals("abc:123", result.value); } public void testKeyDeserializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setHandlerInstantiator(new MyInstantiator("abc:")); MyMap map = mapper.readValue("{\"a\":\"b\"}", MyMap.class); // easiest to test by just serializing... assertEquals("{\"KEY\":\"b\"}", mapper.writeValueAsString(map)); } public void testSerializer() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setHandlerInstantiator(new MyInstantiator("xyz:")); assertEquals(quote("xyz:456"), mapper.writeValueAsString(new MyBean("456"))); } public void testTypeIdResolver() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setHandlerInstantiator(new MyInstantiator("foobar")); String json = mapper.writeValueAsString(new TypeIdBeanWrapper(new TypeIdBean(123))); // should now use our custom id scheme: assertEquals("{\"bean\":[\"!!!\",{\"x\":123}]}", json); // and bring it back too: TypeIdBeanWrapper result = mapper.readValue(json, TypeIdBeanWrapper.class); TypeIdBean bean = result.bean; assertEquals(123, bean.x); } }