java - serialize - Cómo escribir un serializador catch-all(de) para Jackson
objectmapper writevalueasstring (1)
Puede establecer un BeanSerializerModifier para que ObjectMapper
sobrescriba todos los serializadores de beans en su serializador delegante que decide qué forma de serialización usar dependiendo del tipo de objeto.
Aquí hay un ejemplo:
public class JacksonSerializerModifier {
public static interface A {
}
public static class B implements A {
public String field1 = "value1";
@Override
public String toString() {
return field1;
}
}
public static class C implements A {
public String field2 = "value2";
@Override
public String toString() {
return field2;
}
}
public static class D {
public String field3 = "value3";
}
private static class MyTypeSerializer extends JsonSerializer<Object> {
private final JsonSerializer<Object> delegate;
@SuppressWarnings("unchecked")
public MyTypeSerializer(JsonSerializer<?> delegate) {
this.delegate = (JsonSerializer<Object>) delegate;
}
@Override
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
if (value instanceof A) {
jgen.writeString(value.toString());
} else {
delegate.serialize(value, jgen, provider);
}
}
}
public static void main(String[] args) throws JsonProcessingException {
SimpleModule module = new SimpleModule();
module.setSerializerModifier(new BeanSerializerModifier() {
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config,
BeanDescription beanDesc,
JsonSerializer<?> serializer) {
return new MyTypeSerializer(serializer);
}
});
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
System.out.println(mapper.writeValueAsString(Arrays.asList(new B(), new C(), new D())));
}
}
Salida:
["value1","value2",{"field3":"value3"}]
Escribir un serializador personalizado es bastante fácil cuando conoces el tipo por adelantado. Por ej. MyType
uno puede escribir un MyTypeSerializer extends StdSerializer<MyType>
. Ver http://wiki.fasterxml.com/JacksonHowToCustomSerializers
Pero, digamos eso:
- Tengo objetos de varios tipos (interfaces) pasando por la serialización de Jackson.
- No sé el tipo de objetos de tesis por adelantado.
- No puedo agregar anotaciones sobre estos tipos.
- todos los objetos de tesis se pueden convertir a un tipo común que conozco para que pueda obtener sus datos de estado, tipo que no es parte de su interfaz.
Esto significa que necesito escribir un Serializador que debe manejar todos los tipos ("catch-all") y puedo decidir si lo soporta (4.). Intenté ingenuamente que CatchAllSerializer extends StdSerializer<Object>
pero no se activó en absoluto.
¿Cómo se puede escribir / registrar un serializador que capture todos los tipos, pueda decidir si es compatible con un tipo determinado y proporcionar un mecanismo de serialización?