package com.fasterxml.jackson.databind.ser;
import java.io.IOException;
import java.util.*;
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
/**
* This unit test suite tests use of @JsonClass Annotation
* with bean serialization.
*/
public class TestJsonSerialize
extends BaseMapTest
{
/*
/**********************************************************
/* Annotated helper classes
/**********************************************************
*/
interface ValueInterface {
public int getX();
}
static class ValueClass
implements ValueInterface
{
@Override
public int getX() { return 3; }
public int getY() { return 5; }
}
/**
* Test class to verify that <code>JsonSerialize.as</code>
* works as expected
*/
static class WrapperClassForAs
{
@JsonSerialize(as=ValueInterface.class)
public ValueClass getValue() {
return new ValueClass();
}
}
// This should indicate that static type be used for all fields
@JsonSerialize(typing=JsonSerialize.Typing.STATIC)
static class WrapperClassForStaticTyping
{
public ValueInterface getValue() {
return new ValueClass();
}
}
static class WrapperClassForStaticTyping2
{
@JsonSerialize(typing=JsonSerialize.Typing.STATIC)
public ValueInterface getStaticValue() {
return new ValueClass();
}
@JsonSerialize(typing=JsonSerialize.Typing.DYNAMIC)
public ValueInterface getDynamicValue() {
return new ValueClass();
}
}
/**
* Test bean that has an invalid {@link JsonSerialize} annotation.
*/
static class BrokenClass
{
// invalid annotation: String not a supertype of Long
@JsonSerialize(as=String.class)
public Long getValue() {
return Long.valueOf(4L);
}
}
@SuppressWarnings("serial")
static class ValueMap extends HashMap<String,ValueInterface> { }
@SuppressWarnings("serial")
static class ValueList extends ArrayList<ValueInterface> { }
@SuppressWarnings("serial")
static class ValueLinkedList extends LinkedList<ValueInterface> { }
// Classes for [JACKSON-294]
static class Foo294
{
@JsonProperty private String id;
@JsonSerialize(using = Bar294Serializer.class)
private Bar294 bar;
public Foo294() { }
public Foo294(String id, String id2) {
this.id = id;
bar = new Bar294(id2);
}
}
static class Bar294{
@JsonProperty protected String id;
@JsonProperty protected String name;
public Bar294() { }
public Bar294(String id) {
this.id = id;
}
public String getId() { return id; }
public String getName() { return name; }
}
static class Bar294Serializer extends JsonSerializer<Bar294>
{
@Override
public void serialize(Bar294 bar, JsonGenerator jgen,
SerializerProvider provider) throws IOException
{
jgen.writeString(bar.id);
}
}
/*
/**********************************************************
/* Main tests
/**********************************************************
*/
final ObjectMapper MAPPER = objectMapper();
@SuppressWarnings("unchecked")
public void testSimpleValueDefinition() throws Exception
{
Map<String,Object> result = writeAndMap(MAPPER, new WrapperClassForAs());
assertEquals(1, result.size());
Object ob = result.get("value");
// Should see only "x", not "y"
result = (Map<String,Object>) ob;
assertEquals(1, result.size());
assertEquals(Integer.valueOf(3), result.get("x"));
}
public void testBrokenAnnotation() throws Exception
{
try {
serializeAsString(MAPPER, new BrokenClass());
fail("Should not succeed");
} catch (Exception e) {
verifyException(e, "types not related");
}
}
@SuppressWarnings("unchecked")
public void testStaticTypingForClass() throws Exception
{
Map<String,Object> result = writeAndMap(MAPPER, new WrapperClassForStaticTyping());
assertEquals(1, result.size());
Object ob = result.get("value");
// Should see only "x", not "y"
result = (Map<String,Object>) ob;
assertEquals(1, result.size());
assertEquals(Integer.valueOf(3), result.get("x"));
}
@SuppressWarnings("unchecked")
public void testMixedTypingForClass() throws Exception
{
Map<String,Object> result = writeAndMap(MAPPER, new WrapperClassForStaticTyping2());
assertEquals(2, result.size());
Object obStatic = result.get("staticValue");
// Should see only "x", not "y"
Map<String,Object> stat = (Map<String,Object>) obStatic;
assertEquals(1, stat.size());
assertEquals(Integer.valueOf(3), stat.get("x"));
Object obDynamic = result.get("dynamicValue");
// Should see both
Map<String,Object> dyn = (Map<String,Object>) obDynamic;
assertEquals(2, dyn.size());
assertEquals(Integer.valueOf(3), dyn.get("x"));
assertEquals(Integer.valueOf(5), dyn.get("y"));
}
public void testStaticTypingWithMap() throws Exception
{
ObjectMapper m = new ObjectMapper();
m.configure(MapperFeature.USE_STATIC_TYPING, true);
ValueMap map = new ValueMap();
map.put("a", new ValueClass());
assertEquals("{\"a\":{\"x\":3}}", serializeAsString(m, map));
}
public void testStaticTypingWithArrayList() throws Exception
{
ObjectMapper m = new ObjectMapper();
m.configure(MapperFeature.USE_STATIC_TYPING, true);
ValueList list = new ValueList();
list.add(new ValueClass());
assertEquals("[{\"x\":3}]", m.writeValueAsString(list));
}
public void testStaticTypingWithLinkedList() throws Exception
{
ObjectMapper m = new ObjectMapper();
m.configure(MapperFeature.USE_STATIC_TYPING, true);
ValueLinkedList list = new ValueLinkedList();
list.add(new ValueClass());
assertEquals("[{\"x\":3}]", serializeAsString(m, list));
}
public void testStaticTypingWithArray() throws Exception
{
ObjectMapper m = new ObjectMapper();
m.configure(MapperFeature.USE_STATIC_TYPING, true);
ValueInterface[] array = new ValueInterface[] { new ValueClass() };
assertEquals("[{\"x\":3}]", serializeAsString(m, array));
}
public void testIssue294() throws Exception
{
assertEquals("{\"id\":\"fooId\",\"bar\":\"barId\"}",
MAPPER.writeValueAsString(new Foo294("fooId", "barId")));
}
@JsonPropertyOrder({ "a", "something" })
static class Response {
public String a = "x";
@JsonProperty //does not show up
public boolean isSomething() { return true; }
}
public void testWithIsGetter() throws Exception
{
ObjectMapper m = new ObjectMapper();
m.setVisibility(PropertyAccessor.GETTER, Visibility.NONE)
.setVisibility(PropertyAccessor.FIELD, Visibility.ANY)
.setVisibility(PropertyAccessor.CREATOR, Visibility.NONE)
.setVisibility(PropertyAccessor.IS_GETTER, Visibility.NONE)
.setVisibility(PropertyAccessor.SETTER, Visibility.NONE);
final String JSON = m.writeValueAsString(new Response());
assertEquals(aposToQuotes("{'a':'x','something':true}"), JSON);
}
}