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);
}
}