JSON-Jackson - Ausnahme beim serialisieren eine polymorphe Klasse mit benutzerdefinierte serializer
Ich bin derzeit migrieren von code aus Jackson 1.x Jackson 2.5 json-mapper und einen langen ein problem, das nicht da war in 1.x.
Dies ist die setup (siehe code unten):
- Schnittstelle IPet
- class Hund implements IPet
- IPet ist annotiert mit @JsonTypeInfo und @JsonSubTypes
- Klasse Mensch hat eine Eigenschaft mit dem Typ " IPet ist annotiert mit @JsonSerialize(using=CustomPetSerializer.class)
Das problem:
Wenn ich serialisieren wird eine Instanz der Hund es funktioniert wie erwartet (auch die Typ-info Hinzugefügt, um die json-string von Jackson).
Wenn ich mir jedoch die Serialisierung einer Instanz des Menschlichen Klasse eine exception geworfen wird sagen:
com.fasterxml.jackson.databind-Methode.JsonMappingException: Typ-id-handling
nicht implementiert für Typ com.pet.Hund (über die Referenz-Kette:
com.Menschlichen["pet"])
Die serialize (...) - Methode der CustomPetSerializer Klasse wird nicht aufgerufen (getestet mit einem Haltepunkt).
Code:
IPet Umsetzung:
@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();
}
Hund Implementierung:
public class Dog implements IPet
{
@Override
public String getPetMakes()
{
return "Wuff!";
}
@Override
public Long getId()
{
return 777L;
}
}
Mensch besitzt einen Hund:
public class Human
{
private IPet pet = new Dog();
@JsonSerialize(using=CustomPetSerializer.class)
public IPet getPet()
{
return pet;
}
}
CustomPetSerializer Umsetzung:
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-test Methode:
@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\""));
}
Du musst angemeldet sein, um einen Kommentar abzugeben.
Müssen Sie zusätzlich überschreiben
serializeWithType
innerhalb SieCustomPetSerializer
weilIPet
ist polymorph. Das ist auch der Grund, warumserialize
ist nicht genannt. Überprüfen Sie in diesem Zusammenhang Frage ALSO, das erklärt im detail, wennserializeWithType
genannt wird. Zum Beispiel, IhreserializeWithType
Implementierung könnte wie folgt Aussehen:die print
{"pet":{"type":"dog":{"age":"7"}}}
für IhreHuman
Instanz.Da Jackson 2.9
writeTypePrefixForObject()
undwriteTypeSuffixForObject()
wurden abgelehnt (ich bin mir unklar, warum). Es scheint unter dem neuen Konzept würde es jetzt werden:Also eine zusätzliche Zeile, so dass nicht sicher, warum es ist ein Schritt nach vorn, vielleicht ist es effizienter Wiederverwendung der
typeId
Objekt.Quelle: Jacksons ObjectNode Klasse derzeit im master. Nicht die beste Quelle, aber konnte nicht sehen, alle upgrade-docs, die erklären, was zu tun ist.