Reputation: 2506
I have a POJO to be serialized which has field of type Object
named representation
and I have a custom serializer written for it.
POJO:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "user", propOrder = {
//......
})
public class User {
protected User.Event userEvent;
protected Boolean isValid;
protected Boolean isPrivleged;
// getter/ setters
// Inner static class
public static class Event {
protected Object representation;
protected User.Event.Monitor userMonitor;
// getter setters and Monitor static class
}
}
Now, I cannot edit my POJO for some reason, so I want all configurations of Jackson in code via ObjectMapper
. I am not able to register my custom serializer for field Object representation
as it handles type Object
which is a super class for all.
public class CustomSerializer extends JsonSerializer<Object>{
@Override
public void serialize(Object obj, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeObject(content);
// ...........
}
@Override
public Class<Object> handledType() {
return Object.class;
}
}
This gives exception:
java.lang.IllegalArgumentException: JsonSerializer of type CustomSerializer does not define valid handledType() -- must either register with method that takes type argument or make serializer extend 'com.fasterxml.jackson.databind.ser.std.StdSerializer'
at com.fasterxml.jackson.databind.module.SimpleSerializers.addSerializer(SimpleSerializers.java:80)
at com.fasterxml.jackson.databind.module.SimpleModule.addSerializer(SimpleModule.java:240)
So I guess since every field has superclass Object
, thus it's saying invalid handleType().
Is there a way to register a Serializer programtically via the fieled name or something. Eg When field name is representation
register my serializer for it ??
How to handle the above case ??
Upvotes: 3
Views: 4389
Reputation: 3312
Just to add to the excellent answer by cassiomolin if you're trying to use this with Spring Boot and Kotlin to use your custom Jackson ObjectMapper:
// the custom serializer
class CustomSerializer : JsonSerializer<Any>() {
override fun serialize(value: Any?,
gen: JsonGenerator?,
serializers: SerializerProvider?) {
gen?.let {
gen.writeObject(content)
// ...
}
}
}
// the mixin
interface EventMixIn {
@JsonProperty("representation")
@JsonSerialize(using = CustomSerializer::class)
fun getRepresentation(): Any?
}
// the config with the bean
@Configuration
class AppConfig {
@Bean
fun createObjectMapper(): MappingJackson2HttpMessageConverter {
val objectMapper = ObjectMapper()
objectMapper.addMixIn(Event::class.java, EventMixIn::class.java)
return MappingJackson2HttpMessageConverter(objectMapper)
}
}
Upvotes: 1
Reputation: 130837
Have you ever considered Jackson mix-in annotations?
It's a great alternative when modifying the classes is not an option. You can think of it as kind of aspect-oriented way of adding more annotations during runtime, to augment statically defined ones.
Define a mix-in annotation interface (class would do as well):
public interface EventMixIn {
@JsonProperty("representation")
@JsonSerialize(using = CustomSerializer.class)
Object getRepresentation();
}
Then configure ObjectMapper
to use the defined interface as a mix-in for your POJO:
ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT)
.addMixIn(User.Event.class, EventMixIn.class);
Here are some usage considerations:
private
, protected
, ...) and method implementations are ignored.For more details, you can have a look at this page.
Upvotes: 2