杰克逊自定义序列化器的字段名称?

时间:2016-08-11 04:53:25

标签: java json serialization jackson objectmapper

我有一个要序列化的POJO,其中Object类型的字段名为representation,我为它编写了一个自定义序列化程序。

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,这是所有人的超类。

    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)

所以我想因为每个字段都有超类Object,所以它说的是无效的handleType()。

有没有办法通过 fieled name 或其他程序以编程方式注册Serializer。例如,当字段名称representation注册我的序列化器时?

如何处理上述情况?

2 个答案:

答案 0 :(得分:2)

你有没有考虑过 Jackson混合注释

Jackson混合注释

当修改类不是一个选项时,它是一个很好的选择。您可以将其视为在运行时添加更多注释的面向方面的方式,以增加静态定义的注释。

定义混合注释界面(类也可以):

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); 

使用注意事项

以下是一些使用注意事项:

  • 杰克逊认可的所有注释集都可以混合使用。
  • 可以混合使用各种注释(成员方法,静态方法,字段,构造函数注释)。
  • 只有方法(和字段)名称和签名用于匹配注释:访问定义(privateprotected,...)和方法实现被忽略。

有关详细信息,您可以查看此page

答案 1 :(得分:1)

如果要在Spring Boot和Kotlin上使用它来自定义杰克逊ObjectMapper,只需在excellent answer处添加到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)
  }
}