Java 在运行时设置序列化属性

Java 在运行时设置序列化属性,java,serialization,jackson,Java,Serialization,Jackson,在序列化MyObject时,我希望在运行时决定属性类中是否包含null属性。最好的方法是什么 import com.fasterxml.jackson.annotation.JsonInclude; import lombok.Data; @Data @JsonInclude(JsonInclude.Include.NON_NULL) public class MyObject { private String property1; private DateTime property2

在序列化MyObject时,我希望在运行时决定属性类中是否包含null属性。最好的方法是什么

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MyObject {
  private String property1;
  private DateTime property2;
  private Attributes attributes;
}

@Data
public class Attributes {
  private String property1;
  private String property2;
}

您可以在映射器中更改该行为:

if (noNull) {
   mapper.setSerializationInclusion(Include.NON_NULL);
} else {
   mapper.setSerializationInclusion(Include.ALWAYS);
}

您可以在映射器中更改该行为:

if (noNull) {
   mapper.setSerializationInclusion(Include.NON_NULL);
} else {
   mapper.setSerializationInclusion(Include.ALWAYS);
}

如果您使用的是Jackson 2.8,那么您可以使用新的“配置覆盖”功能(在f.ex的高级讨论中)来指定注释的等效项,如下所示:

mapper.configOverride(Attributes.class)
    // first value for value itself (POJO); second value only relevant
    // for structured types like Map/Collection/array/Optional
    .setInclude(JsonInclude.Value.construct(Include.NON_NULL, null));
(以及以前仅使用注释提供的一些其他方面)

但是,请注意,与注释一样,此设置在初始设置后不能更改:必须为
ObjectMapper
定义一次,进一步的更改将不会生效。
如果您需要不同配置的映射器,则需要创建不同的实例。

如果您使用的是Jackson 2.8,则可以使用新的“配置覆盖”功能(在f.ex的高级讨论中)来指定注释的等效项,如下所示:

mapper.configOverride(Attributes.class)
    // first value for value itself (POJO); second value only relevant
    // for structured types like Map/Collection/array/Optional
    .setInclude(JsonInclude.Value.construct(Include.NON_NULL, null));
(以及以前仅使用注释提供的一些其他方面)

但是,请注意,与注释一样,此设置在初始设置后不能更改:必须为
ObjectMapper
定义一次,进一步的更改将不会生效。
如果需要不同配置的映射器,则需要创建不同的实例。

根据运行时决策控制的细粒度,有几种可能性

  • 如果在运行时行为完全是自定义的,则您可以使用自己的自定义筛选器来执行复杂的决策,以序列化字段或不序列化字段。过滤器的外观如下所示:

    PropertyFilter myFilter = new SimpleBeanPropertyFilter() {
        @Override public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) throws Exception {
    
            boolean needsSerialization = needsSerializationBasedOnAdvancedRuntimeDecision((MyValueObject) pojo, writer.getName());
    
               if (needsSerialization){
                    writer.serializeAsField(pojo, jgen, provider);
               }
    
        }
    
        @Override protected boolean include(BeanPropertyWriter writer) { return true; }
        @Override protected boolean include(PropertyWriter writer) { return true; }
    };
    
    可以逐个属性处理序列化决策,例如:

    private boolean needsSerializationBasedOnAdvancedRuntimeDecision(MyValueObject myValueObject, String name) {
        return !"property1".equals(name) || ( myValueObject.getProperty1() == null && property1NullSerializationEnabled );
    }
    
    然后,您可以应用所需的过滤器,如下所示:

    FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter", myFilter);
    
    String json = new ObjectMapper().writer(filters).writeValueAsString(myValueObject);
    
  • 如果类的属性的行为相同,则使用
    @JsonInclude(JsonInclude.Include.NON_NULL)

  • 如果整个类的行为相同(例如属性),请使用
    @JsonInclude(JsonInclude.Include.NON_NULL)
    或所述的配置覆盖配置该类

     @JsonInclude(JsonInclude.Include.NON_NULL) 
     public class Attributes {
        private String property1;
        private String property2;
     }
    
  • 如果当前映射的所有类的行为都是相同的:按原样配置映射器


    • 根据您的运行时决策控制需要的细粒度,有几种可能性

      • 如果在运行时行为完全是自定义的,则您可以使用自己的自定义筛选器来执行复杂的决策,以序列化字段或不序列化字段。过滤器的外观如下所示:

        PropertyFilter myFilter = new SimpleBeanPropertyFilter() {
            @Override public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) throws Exception {
        
                boolean needsSerialization = needsSerializationBasedOnAdvancedRuntimeDecision((MyValueObject) pojo, writer.getName());
        
                   if (needsSerialization){
                        writer.serializeAsField(pojo, jgen, provider);
                   }
        
            }
        
            @Override protected boolean include(BeanPropertyWriter writer) { return true; }
            @Override protected boolean include(PropertyWriter writer) { return true; }
        };
        
        可以逐个属性处理序列化决策,例如:

        private boolean needsSerializationBasedOnAdvancedRuntimeDecision(MyValueObject myValueObject, String name) {
            return !"property1".equals(name) || ( myValueObject.getProperty1() == null && property1NullSerializationEnabled );
        }
        
        然后,您可以应用所需的过滤器,如下所示:

        FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter", myFilter);
        
        String json = new ObjectMapper().writer(filters).writeValueAsString(myValueObject);
        
      • 如果类的属性的行为相同,则使用
        @JsonInclude(JsonInclude.Include.NON_NULL)

      • 如果整个类的行为相同(例如属性),请使用
        @JsonInclude(JsonInclude.Include.NON_NULL)
        或所述的配置覆盖配置该类

         @JsonInclude(JsonInclude.Include.NON_NULL) 
         public class Attributes {
            private String property1;
            private String property2;
         }
        
      • 如果当前映射的所有类的行为都是相同的:按原样配置映射器


      但我只需要在
      属性中执行条件包含null,而不需要在
      MyObject
      类中执行。如果类已经具有JsonIgnore注释,这可能不起作用,因为objectMapper设置被认为是全局的,并且具有该注释的类将获得首选项,但我需要执行条件包含null在
      Attributes
      类中,而不是在
      MyObject
      类中。如果类已具有JsonIgnore注释,则这可能不起作用,因为objectMapper设置被视为全局设置,并且具有该注释的类将获得首选项