Je souhaite créer un sérialiseur personnalisé qui effectue un travail minime, puis laisse le reste pour la sérialisation par défaut.
Par exemple:
@JsonSerialize(using = MyClassSerializer.class)
public class MyClass {
...
}
public class MyClassSerializer extends JsonSerializer<MyClass> {
@Override
public void serialize(MyClass myClass, JsonGenerator generator,
SerializerProvider provider)
throws JsonGenerationException, IOException {
if (myClass.getSomeProperty() == someCalculationResult) {
provider.setAttribute("special", true);
}
generator.writeObject(myClass);
}
}
Avec l'idée de créer d'autres sérialiseurs personnalisés pour les objets agrégés qui se comportent différemment en fonction de la valeur de l'attribut "speical". Cependant, le code ci-dessus ne fonctionne pas, car il entre sans surprise dans une récursion infinie.
Y a-t-il un moyen de dire à Jackson d'utiliser la sérialisation par défaut une fois l'attribut défini? Je ne veux pas vraiment énumérer toutes les propriétés, comme beaucoup de sérialiseurs personnalisés, car la classe est assez complexe et je ne souhaite pas avoir à effectuer une double maintenance avec le sérialiseur chaque fois que je change de classe.
UnBeanSerializerModifier
vous donnera accès à la sérialisation par défaut.
public class MyClassSerializer extends JsonSerializer<MyClass> {
private final JsonSerializer<Object> defaultSerializer;
public MyClassSerializer(JsonSerializer<Object> defaultSerializer) {
this.defaultSerializer = checkNotNull(defaultSerializer);
}
@Override
public void serialize(MyClass myclass, JsonGenerator gen, SerializerProvider provider) throws IOException {
if (myclass.getSomeProperty() == true) {
provider.setAttribute("special", true);
}
defaultSerializer.serialize(myclass, gen, provider);
}
}
BeanSerializerModifier
pour MyClass
public class MyClassSerializerModifier extends BeanSerializerModifier {
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
if (beanDesc.getBeanClass() == MySpecificClass.class) {
return new MyClassSerializer((JsonSerializer<Object>) serializer);
}
return serializer;
}
}
ObjectMapper om = new ObjectMapper()
.registerModule(new SimpleModule()
.setSerializerModifier(new MyClassSerializerModifier()));
@JsonSerialize(using = MyClassSerializer.class)
public class MyClass {
...
}
public class MyClassSerializer extends JsonSerializer<MyClass> {
@Override
public void serialize(MyClass myClass, JsonGenerator generator,
SerializerProvider provider)
throws JsonGenerationException, IOException {
if (myClass.getSomeProperty() == someCalculationResult) {
provider.setAttribute("special", true);
}
provider.defaultSerializeValue(myClass, generator);
}
}
si vous écrivez simplement un objet comme d'habitude, utilisez ce qui précède
Pour ajouter à la réponse choisie, l’implémentation du sérialiseur peut également devoir implémenter les interfaces ContextualSerializer
et ResolvableSerializer
. Jetez un coup d’œil à un problème connexe ici https://github.com/FasterXML/jackson-dataformat-xml/issues/259
public class MyClassSerializer extends JsonSerializer<MyClass>
implements ContextualSerializer, ResolvableSerializer {
private final JsonSerializer<Object> defaultSerializer;
public MyClassSerializer(JsonSerializer<Object> defaultSerializer) {
this.defaultSerializer = checkNotNull(defaultSerializer);
}
@Override
public void serialize(MyClass myclass, JsonGenerator gen, SerializerProvider provider)
throws IOException {
if (myclass.getSomeProperty() == true) {
provider.setAttribute("special", true);
}
defaultSerializer.serialize(myclass, gen, provider);
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
throws JsonMappingException {
if (defaultSerializer instanceof ContextualSerializer) {
JsonSerializer<?> contextual = ((ContextualSerializer)defaultSerializer).createContextual(prov, property);
return new MyClassSerializer((JsonSerializer<Object>)contextual);
}
return new MyClassSerializer(defaultSerializer);
}
@Override
public void resolve(SerializerProvider provider) throws JsonMappingException {
if (defaultSerializer instanceof ResolvableSerializer) {
((ResolvableSerializer)defaultSerializer).resolve(provider);
}
}
}
Vous pouvez utiliser @JsonGetter au lieu d'utiliser un sérialiseur personnalisé si c'est le seul changement que vous souhaitez apporter.
public class MyClass{
@JsonGetter("special")
protected boolean getSpecialForJackson() {
return myClass.getSomeProperty() == someCalculationResult;
}
}