blob: 353b2bb8bb6cd6f7f203b14009163ef9ada2f8a6 [file] [log] [blame]
package org.codehaus.jackson.map.ser;
import java.io.IOException;
import java.util.*;
import org.codehaus.jackson.*;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonPropertyOrder;
import org.codehaus.jackson.map.*;
import org.codehaus.jackson.map.introspect.BasicBeanDescription;
import org.codehaus.jackson.map.module.SimpleModule;
import org.codehaus.jackson.type.JavaType;
/**
* Unit tests for verifying that it is possible to configure
* construction of {@link BeanSerializer} instances.
*
* @since 1.7
*/
public class TestBeanSerializer extends BaseMapTest
{
/*
/********************************************************
/* Helper types
/********************************************************
*/
static class ModuleImpl extends SimpleModule
{
protected BeanSerializerModifier modifier;
public ModuleImpl(BeanSerializerModifier modifier)
{
super("test", Version.unknownVersion());
this.modifier = modifier;
}
@Override
public void setupModule(SetupContext context)
{
super.setupModule(context);
if (modifier != null) {
context.addBeanSerializerModifier(modifier);
}
}
}
@JsonPropertyOrder({"b", "a"})
static class Bean {
public String b = "b";
public String a = "a";
}
static class RemovingModifier extends BeanSerializerModifier
{
private final String _removedProperty;
public RemovingModifier(String remove) { _removedProperty = remove; }
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BasicBeanDescription beanDesc,
List<BeanPropertyWriter> beanProperties)
{
Iterator<BeanPropertyWriter> it = beanProperties.iterator();
while (it.hasNext()) {
BeanPropertyWriter bpw = it.next();
if (bpw.getName().equals(_removedProperty)) {
it.remove();
}
}
return beanProperties;
}
}
static class ReorderingModifier extends BeanSerializerModifier
{
@Override
public List<BeanPropertyWriter> orderProperties(SerializationConfig config, BasicBeanDescription beanDesc, List<BeanPropertyWriter> beanProperties)
{
TreeMap<String,BeanPropertyWriter> props = new TreeMap<String,BeanPropertyWriter>();
for (BeanPropertyWriter bpw : beanProperties) {
props.put(bpw.getName(), bpw);
}
return new ArrayList<BeanPropertyWriter>(props.values());
}
}
static class ReplacingModifier extends BeanSerializerModifier
{
private final JsonSerializer<?> _serializer;
public ReplacingModifier(JsonSerializer<?> s) { _serializer = s; }
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config, BasicBeanDescription beanDesc,
JsonSerializer<?> serializer) {
return _serializer;
}
}
static class BuilderModifier extends BeanSerializerModifier
{
private final JsonSerializer<?> _serializer;
public BuilderModifier(JsonSerializer<?> ser) {
_serializer = ser;
}
@Override
public BeanSerializerBuilder updateBuilder(SerializationConfig config,
BasicBeanDescription beanDesc, BeanSerializerBuilder builder) {
return new BogusSerializerBuilder(builder, _serializer);
}
}
static class BogusSerializerBuilder extends BeanSerializerBuilder
{
private final JsonSerializer<?> _serializer;
public BogusSerializerBuilder(BeanSerializerBuilder src,
JsonSerializer<?> ser) {
super(src);
_serializer = ser;
}
@Override
public JsonSerializer<?> build() {
return _serializer;
}
}
static class BogusBeanSerializer extends JsonSerializer<Object>
{
private final int _value;
public BogusBeanSerializer(int v) { _value = v; }
@Override
public void serialize(Object value, JsonGenerator jgen,
SerializerProvider provider) throws IOException {
jgen.writeNumber(_value);
}
}
// for [JACKSON-670]
static class EmptyBean {
@JsonIgnore
public String name = "foo";
}
static class EmptyBeanModifier extends BeanSerializerModifier
{
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
BasicBeanDescription beanDesc, List<BeanPropertyWriter> beanProperties)
{
JavaType strType = config.constructType(String.class);
try {
beanProperties.add(new BeanPropertyWriter(
null, null,
"bogus", strType,
null, null, strType,
null, EmptyBean.class.getDeclaredField("name"),
false, null
));
} catch (NoSuchFieldException e) {
throw new IllegalStateException(e.getMessage());
}
return beanProperties;
}
}
// For [JACKSON-694]: error message for conflicting getters sub-optimal
static class BeanWithConflict
{
public int getX() { return 3; }
public boolean isX() { return false; }
}
/*
/********************************************************
/* Unit tests: success
/********************************************************
*/
public void testPropertyRemoval() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new ModuleImpl(new RemovingModifier("a")));
Bean bean = new Bean();
assertEquals("{\"b\":\"b\"}", mapper.writeValueAsString(bean));
}
public void testPropertyReorder() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new ModuleImpl(new ReorderingModifier()));
Bean bean = new Bean();
assertEquals("{\"a\":\"a\",\"b\":\"b\"}", mapper.writeValueAsString(bean));
}
public void testBuilderReplacement() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new ModuleImpl(new BuilderModifier(new BogusBeanSerializer(17))));
Bean bean = new Bean();
assertEquals("17", mapper.writeValueAsString(bean));
}
public void testSerializerReplacement() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new ModuleImpl(new ReplacingModifier(new BogusBeanSerializer(123))));
Bean bean = new Bean();
assertEquals("123", mapper.writeValueAsString(bean));
}
// for [JACKSON-670]
public void testEmptyBean() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SimpleModule("test", Version.unknownVersion()) {
@Override
public void setupModule(SetupContext context)
{
super.setupModule(context);
context.addBeanSerializerModifier(new EmptyBeanModifier());
}
});
String json = mapper.writeValueAsString(new EmptyBean());
assertEquals("{\"bogus\":\"foo\"}", json);
}
/*
/********************************************************
/* Unit tests: failure handling
/********************************************************
*/
// for [JACKSON-694]
public void testFailWithDupProps() throws Exception
{
BeanWithConflict bean = new BeanWithConflict();
ObjectMapper mapper = new ObjectMapper();
try {
String json = mapper.writeValueAsString(bean);
fail("Should have failed due to conflicting accessor definitions; got JSON = "+json);
} catch (JsonProcessingException e) {
verifyException(e, "Conflicting getter definitions");
}
}
}