MappingJackson2HttpMessageConverter 分类别处理null

jackson并没有提供分类别处理null,jackson的核心类ObjectMapper暴露的NullSerializer无法针对不同类型设定不同的默认值,所幸jackson有完善的扩展机制。BeanSerializerModifierchangeProperties()方法提供了细粒度控制每个Field的序列化行为的可能,代码如下。

public enum SerializerFeature {
   WriteNullListAsEmpty,
   WriteNullStringAsEmpty,
   WriteNullNumberAsZero,
   WriteNullBooleanAsFalse;
   
   public final int mask;
   
   SerializerFeature() {
       mask = (1 << ordinal());
   }
}

final public static class FastJsonSerializerFeatureCompatibleForJackson extends BeanSerializerModifier {
   final private JsonSerializer nullBooleanJsonSerializer;
   final private JsonSerializer nullNumberJsonSerializer;
   final private JsonSerializer nullListJsonSerializer;
   final private JsonSerializer nullStringJsonSerializer;
   
   FastJsonSerializerFeatureCompatibleForJackson(SerializerFeature... features) {
       int config = 0;
       for (SerializerFeature feature : features) {
           config |= feature.mask;
       }
       nullBooleanJsonSerializer = (config & WriteNullBooleanAsFalse.mask) != 0 ? new NullBooleanSerializer() : null;
       nullNumberJsonSerializer = (config & WriteNullNumberAsZero.mask) != 0 ? new NullNumberSerializer() : null;
       nullListJsonSerializer = (config & WriteNullListAsEmpty.mask) != 0 ? new NullListJsonSerializer() : null;
       nullStringJsonSerializer = (config & WriteNullStringAsEmpty.mask) != 0 ? new NullStringSerializer() : null;
   }
   
   @Override
   public List changeProperties(SerializationConfig config, BeanDescription beanDesc, List beanProperties) {
       for (BeanPropertyWriter writer : beanProperties) {
           final JavaType javaType = writer.getType();
           final Class rawClass = javaType.getRawClass();
           if (javaType.isArrayType() || javaType.isCollectionLikeType()) {
               writer.assignNullSerializer(nullListJsonSerializer);
           } else if (Number.class.isAssignableFrom(rawClass) && rawClass.getName().startsWith("java.lang")) {
               writer.assignNullSerializer(nullNumberJsonSerializer);
           } else if (Boolean.class.equals(rawClass)) {
               writer.assignNullSerializer(nullBooleanJsonSerializer);
           } else if (String.class.equals(rawClass)) {
               writer.assignNullSerializer(nullStringJsonSerializer);
           }
       }
       return beanProperties;
   }
   
   private static class NullListJsonSerializer extends JsonSerializer {
       @Override
       public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
           jgen.writeStartArray();
           jgen.writeEndArray();
       }
   }
   
   private static class NullNumberSerializer extends JsonSerializer {
       @Override
       public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
           jgen.writeNumber(0);
       }
   }
   
   private static class NullBooleanSerializer extends JsonSerializer {
       @Override
       public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
           jgen.writeBoolean(false);
       }
   }
   
   private static class NullStringSerializer extends JsonSerializer {
       @Override
       public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
           jgen.writeString("");
       }
   }
} 
  最后把该 
  Modifier 
  注入到 
  ObjectMapper 
  中。 
  
objectMapper.setSerializerFactory(objectMapper.getSerializerFactory().withSerializerModifier(new FastJsonSerializerFeatureCompatibleForJackson(features)));

反序列化时忽略不存在的字段

在标准Json规范中,如果尝试反序列化一个Json字符串为指定的POJO,而且字符串中有一个Field在POJO中不存在,应该抛出错误。对于这种情况,fastjson默认是跳过,jackson默认是中止。

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

重新设置SpringMVC的HttpMessageConvertor


      
          
              
                  
                      WriteNullListAsEmpty
                      WriteNullStringAsEmpty
                      WriteNullNumberAsZero
                      WriteNullBooleanAsFalse
                  
              
          
      
  

由于需要编程式的设置全局配置,扩展 FactoryBean CustomObjectMapperFactoryBean )生成自定义的 ObjectMapper 来替代 MappingJackson2HttpMessageConverter 中默认 ObjectMapper
final public static class CustomObjectMapperFactoryBean implements FactoryBean {
 SerializerFeature[] features;
 public CustomObjectMapperFactoryBean(SerializerFeature[] features) {
     this.features = features;
 }

 @Override
 public ObjectMapper getObject() throws Exception {
     ObjectMapper objectMapper = new ObjectMapper();
     objectMapper.setSerializerFactory(objectMapper.getSerializerFactory().withSerializerModifier(new FastJsonSerializerFeatureCompatibleForJackson(features))).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
     return objectMapper;
 }

 @Override
 public Class getObjectType() {
     return ObjectMapper.class;
 }

 @Override
 public boolean isSingleton() {
     return false;
 }
}


你可能感兴趣的:(Java,Java,Srping)