杰克逊按字段名称自定义序列化程序?
Jackson custom serializer by field name?
我有一个要序列化的 POJO,它具有名为 representation
的 Object
类型的字段,并且我有一个为其编写的自定义序列化程序。
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
}
}
现在,出于某种原因我无法编辑我的 POJO,所以我希望通过 ObjectMapper
在代码中对 Jackson 进行所有配置。我无法为字段 Object representation
注册我的自定义序列化程序,因为它处理类型 Object
,它是一个超级 class 所有人。
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;
}
}
这给出了例外:
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)
所以我想因为每个字段都有 superclass Object
,所以它说无效的 handleType()。
有没有办法通过 字段名 或其他方式以编程方式注册序列化程序。例如,当字段名称是 representation
时,为它注册我的序列化程序 ??
如何处理上述情况??
您是否考虑过 Jackson 混合注释?
Jackson 混合注释
当无法修改 classes 时,这是一个很好的选择。您可以将其视为一种在运行时添加更多注释的面向方面的方式,以扩充静态定义的注释。
定义一个混合注释接口(class 也可以):
public interface EventMixIn {
@JsonProperty("representation")
@JsonSerialize(using = CustomSerializer.class)
Object getRepresentation();
}
然后配置 ObjectMapper
以将定义的接口用作您的 POJO 的混合:
ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT)
.addMixIn(User.Event.class, EventMixIn.class);
使用注意事项
以下是一些使用注意事项:
- Jackson识别的所有注释集都可以混入。
- 各种注解(成员方法、静态方法、字段、构造函数注解)都可以混入
- 只有方法(和字段)名称和签名用于匹配注释:访问定义(
private
、protected
、...)和方法实现将被忽略。
更多详情,你可以看看这个page。
如果您尝试将其与 Spring Boot 和 Kotlin 一起使用以使用您的自定义 Jackson ObjectMapper,只需添加到 by cassiomolin:
// 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)
}
}
我有一个要序列化的 POJO,它具有名为 representation
的 Object
类型的字段,并且我有一个为其编写的自定义序列化程序。
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
}
}
现在,出于某种原因我无法编辑我的 POJO,所以我希望通过 ObjectMapper
在代码中对 Jackson 进行所有配置。我无法为字段 Object representation
注册我的自定义序列化程序,因为它处理类型 Object
,它是一个超级 class 所有人。
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;
}
}
这给出了例外:
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)
所以我想因为每个字段都有 superclass Object
,所以它说无效的 handleType()。
有没有办法通过 字段名 或其他方式以编程方式注册序列化程序。例如,当字段名称是 representation
时,为它注册我的序列化程序 ??
如何处理上述情况??
您是否考虑过 Jackson 混合注释?
Jackson 混合注释
当无法修改 classes 时,这是一个很好的选择。您可以将其视为一种在运行时添加更多注释的面向方面的方式,以扩充静态定义的注释。
定义一个混合注释接口(class 也可以):
public interface EventMixIn {
@JsonProperty("representation")
@JsonSerialize(using = CustomSerializer.class)
Object getRepresentation();
}
然后配置 ObjectMapper
以将定义的接口用作您的 POJO 的混合:
ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT)
.addMixIn(User.Event.class, EventMixIn.class);
使用注意事项
以下是一些使用注意事项:
- Jackson识别的所有注释集都可以混入。
- 各种注解(成员方法、静态方法、字段、构造函数注解)都可以混入
- 只有方法(和字段)名称和签名用于匹配注释:访问定义(
private
、protected
、...)和方法实现将被忽略。
更多详情,你可以看看这个page。
如果您尝试将其与 Spring Boot 和 Kotlin 一起使用以使用您的自定义 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)
}
}