Reputation: 3310
I want to change an object just before JSON Serialization. To do it, I've created an interface, with change method, and any class that implements this interface will "try" to change itself. (yes, probably doing it like this is not optimal, but for example sake will do)
@JsonSerialize(using = ChangesValuesSerializer.class)
public interface ChangesValues {
void changeValues();
}
Now, is ChangesValuesSerializer
class I'm implementing serialize
method. And want to know, how can I say Jackson, to call it's built in serializer on object.
class ChangesValuesSerializer extends JsonSerializer<ChangesValues> {
@Override
public void serialize(ChangesValues changesValues, JsonGenerator jsonGenerator,
SerializerProvider serializerProvider) throws IOException,
JsonProcessingException {
changesValues.changeValues();
// ***
// ->> Just call Jacksons default serializer
// ***
}
}
Upvotes: 2
Views: 4104
Reputation: 10853
You can use BeanSerializerModifier
to get the access to the default serializer and override it with your own delegate. Inside the delegate you can change your serialised object and call the default serializer. Here is an example:
public class JacksonSerializeModifier {
public static class Bean {
public final String value;
public Bean(final String value) {
this.value = value;
}
public void foo() {
System.out.println("foo() invoked");
}
}
private static class MyBeanSerializerModifier extends BeanSerializerModifier {
@Override
public JsonSerializer<?> modifySerializer(
final SerializationConfig serializationConfig,
final BeanDescription beanDescription,
final JsonSerializer<?> jsonSerializer) {
return new ModifyingSerializer((JsonSerializer<Object>) jsonSerializer);
}
}
private static class ModifyingSerializer extends JsonSerializer<Object> {
private final JsonSerializer<Object> serializer;
public ModifyingSerializer(final JsonSerializer<Object> jsonSerializer) {
this.serializer = jsonSerializer;
}
@Override
public void serialize(
final Object o,
final JsonGenerator jsonGenerator,
final SerializerProvider serializerProvider)
throws IOException {
if (o instanceof Bean) {
((Bean) o).foo();
}
serializer.serialize(o, jsonGenerator, serializerProvider);
}
}
public static void main(String[] args) throws JsonProcessingException {
SimpleModule module = new SimpleModule();
module.setSerializerModifier(new MyBeanSerializerModifier());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
System.out.println(mapper.writeValueAsString(new Bean("abc")));
}
}
Output:
foo() invoked
{"value":"abc"}
Upvotes: 6
Reputation: 1874
In the event of an abstract class this is not doable.
You could go around it by adding another class that extends JSON serializer (i.e. BasicJSONSerializer) and call the method from there. i.e.
class BasicJSONSerializer extends JsonSerializer<ChangesValues> {}
class ChangesValuesSerializer extends JsonSerializer<ChangesValues> {
@Override
public void serialize(ChangesValues changesValues, JsonGenerator jsonGenerator,
SerializerProvider serializerProvider) throws IOException,
JsonProcessingException {
changesValues.changeValues();
new BasicJSONSerializer().serialize(changesValues, jsonGenerator, serializerProvider);
}
}
but that seems like a hack and honestly a better design might be needed.
Upvotes: 0