package com.fasterxml.jackson.databind.ser;
import java.io.IOException;
import java.io.StringWriter;
import java.util.*;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Element;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.io.CharacterEscapes;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.CollectionSerializer;
import com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer;
import com.fasterxml.jackson.databind.util.StdConverter;
/**
* Tests for verifying various issues with custom serializers.
*/
public class TestCustomSerializers extends BaseMapTest
{
/*
/**********************************************************
/* Helper beans
/**********************************************************
*/
static class ElementSerializer extends JsonSerializer<Element>
{
@Override
public void serialize(Element value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeString("element");
}
}
@JsonSerialize(using = ElementSerializer.class)
public static class ElementMixin {}
public static class Immutable {
protected int x() { return 3; }
protected int y() { return 7; }
}
/**
* Trivial simple custom escape definition set.
*/
@SuppressWarnings("serial")
static class CustomEscapes extends CharacterEscapes
{
private final int[] _asciiEscapes;
public CustomEscapes() {
_asciiEscapes = standardAsciiEscapesForJSON();
_asciiEscapes['a'] = 'A'; // to basically give us "\A" instead of 'a'
_asciiEscapes['b'] = CharacterEscapes.ESCAPE_STANDARD; // too force "\u0062"
}
@Override
public int[] getEscapeCodesForAscii() {
return _asciiEscapes;
}
@Override
public SerializableString getEscapeSequence(int ch) {
return null;
}
}
@JsonFormat(shape=JsonFormat.Shape.OBJECT)
static class LikeNumber extends Number {
private static final long serialVersionUID = 1L;
public int x;
public LikeNumber(int value) { x = value; }
@Override
public double doubleValue() {
return x;
}
@Override
public float floatValue() {
return x;
}
@Override
public int intValue() {
return x;
}
@Override
public long longValue() {
return x;
}
}
/*
/**********************************************************
/* Unit tests
/**********************************************************
*/
private final ObjectMapper MAPPER = new ObjectMapper();
public void testCustomization() throws Exception
{
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.addMixIn(Element.class, ElementMixin.class);
Element element = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument().createElement("el");
StringWriter sw = new StringWriter();
objectMapper.writeValue(sw, element);
assertEquals(sw.toString(), "\"element\"");
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public void testCustomLists() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule("test", Version.unknownVersion());
JsonSerializer<?> ser = new CollectionSerializer(null, false, null, null, null);
final JsonSerializer<Object> collectionSerializer = (JsonSerializer<Object>) ser;
module.addSerializer(Collection.class, new JsonSerializer<Collection>() {
@Override
public void serialize(Collection value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
if (value.size() != 0) {
collectionSerializer.serialize(value, jgen, provider);
} else {
jgen.writeNull();
}
}
});
mapper.registerModule(module);
assertEquals("null", mapper.writeValueAsString(new ArrayList<Object>()));
}
// [Issue#87]: delegating serializer
public void testDelegating() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule("test", Version.unknownVersion());
module.addSerializer(new StdDelegatingSerializer(Immutable.class,
new StdConverter<Immutable, Map<String,Integer>>() {
@Override
public Map<String, Integer> convert(Immutable value)
{
HashMap<String,Integer> map = new LinkedHashMap<String,Integer>();
map.put("x", value.x());
map.put("y", value.y());
return map;
}
}));
mapper.registerModule(module);
assertEquals("{\"x\":3,\"y\":7}", mapper.writeValueAsString(new Immutable()));
}
// [Issue#215]: Allow registering CharacterEscapes via ObjectWriter
public void testCustomEscapes() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
assertEquals(quote("foo\\u0062\\Ar"),
mapper.writer(new CustomEscapes()).writeValueAsString("foobar"));
}
public void testNumberSubclass() throws Exception
{
assertEquals(aposToQuotes("{'x':42}"),
MAPPER.writeValueAsString(new LikeNumber(42)));
}
}