I am currently porting some code from Jackson 1.x to Jackson 2.5 json mapper and there was a problem that was not in 1.x.
This is the setting (see code below):
- IPet interface
- Dog class implements IPet
- IPet annotated with @JsonTypeInfo and @JsonSubTypes
- class A person has a property of type IPet, which is annotated using @JsonSerialize (using = CustomPetSerializer.class).
Problem: If I serialize a Dog instance, it works as expected (also type information is added to the Jackson json string). However, when I serialize an instance of the Human class, an exception is thrown:
com.fasterxml.jackson.databind.JsonMappingException: type identifier processing is not applied for the com.pet.Dog type (via the reference chain: com.Human ["pet"])
The serialize (...) method of the CustomPetSerializer class is not called (checked using a breakpoint).
The code:
IPet implementation:
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type") @JsonSubTypes({ @JsonSubTypes.Type(value=Dog.class, name="dog") //,@JsonSubTypes.Type(value=Cat.class, name="cat") //more subtypes here... }) public interface IPet { public Long getId(); public String getPetMakes(); }
Dog implementation:
public class Dog implements IPet { @Override public String getPetMakes() { return "Wuff!"; } @Override public Long getId() { return 777L; } }
Dog Owner:
public class Human { private IPet pet = new Dog(); @JsonSerialize(using=CustomPetSerializer.class) public IPet getPet() { return pet; } }
Executing CustomPetSerializer:
public class CustomPetSerializer extends JsonSerializer<IPet> { @Override public void serialize(IPet value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException { if(value != null && value.getId() != null) { Map<String,Object> style = new HashMap<String,Object>(); style.put("age", "7"); gen.writeObject(style); } } }
JUnit validation method:
@Test public void testPet() throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); Human human = new Human(); //works as expcected String json = mapper.writeValueAsString(human.getPet()); Assert.assertNotNull(json); Assert.assertTrue(json.equals("{\"type\":\"dog\",\"id\":777,\"petMakes\":\"Wuff!\"}")); //throws exception: Type id handling not implemented for type com.pet.Dog (through reference chain: com.Human["pet"]) json = mapper.writeValueAsString(human); //exception is thrown here Assert.assertNotNull(json); Assert.assertTrue(json.contains("\"age\":\"7\"")); }