【问题标题】:Jackson deserialize map null values to empty string杰克逊反序列化映射空值到空字符串
【发布时间】:2018-12-13 19:17:43
【问题描述】:

我正在尝试为所有 json Map<String, String> 查找全局 ObjectMapper 配置(或任何其他自定义)以反序列化为没有 null 值的映射(应该有一个空字符串)

例如

class MyClass {
  Map<String, String> dict;

  String str;

  public MyClass() {
  }

  public MyClass(Map<String, String> dict, String str) {
    this.dict = dict;
    this.str = str;
  }

  public Map<String, String> getDict() {
    return dict;
  }

  public String getStr() {
    return str;
  }
}
...

final Map<String, String> dict = new HashMap<>();
dict.put("k1", "v1");
dict.put("k2", null);
final MyClass myClass = new MyClass(dict);
final String valueAsString = objectMapper.writeValueAsString(myClass);
final MyClass deserialized = objectMapper.readValue(valueAsString, MyClass.class);
deserialized.getDict().get("k2"); // = "" (empty String)
deserialized.getStr(); // = null

我知道我可以通过使用 @JsonDeserialize(using = MyDeserializer.class) 注释我的类来完成每个 POJO 但我希望它适用于所有地图。

我也尝试过调整这个 solution 以用于反序列化,但它会抛出 NullPointerException


更新:“空到空”转换需要仅在地图上(使用字符串值)起作用。 (参见上面的更新示例)

【问题讨论】:

    标签: java json dictionary null jackson


    【解决方案1】:

    看看它对我有用:

    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    import org.junit.Test;
    
    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.databind.JsonSerializer;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.SerializerProvider;
    import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider;
    
    public class TestTest {
    
        @Test
        public void test_Map_null_EmptyString_() throws IOException {    
            ObjectMapper mapper = new ObjectMapper();
            DefaultSerializerProvider sp = new DefaultSerializerProvider.Impl();
            sp.setNullValueSerializer(new NullSerializer());
            mapper.setSerializerProvider(sp);
    
            final Map<String, String> dict = new HashMap<>();
            dict.put("k1", "v1");
            dict.put("k2", null);
            final MyClass myClass = new MyClass(dict);
            final String valueAsString = mapper.writeValueAsString(myClass);
            System.out.println(valueAsString);
            final MyClass deserialized = mapper.readValue(valueAsString, MyClass.class);
            System.out.println(deserialized.getDict().get("k2")); // = "" (empty String)
        }
    
        public class NullSerializer extends JsonSerializer<Object> {
            public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
                jgen.writeString("");
            }
        }
    }
    
    class MyClass {
        Map<String, String> dict;
    
        public MyClass() {
        }
    
        public MyClass(Map<String, String> dict) {
            this.dict = dict;
        }
    
        public Map<String, String> getDict() {
            return dict;
        }
    }
    

    【讨论】:

    • 这将替换所有空值,而我需要将其限制为仅映射字符串值。 (见更新的问题)
    【解决方案2】:

    我最终使用了 DeserializerModifier 技术如下:

    static class MapCustomDeserializerModifier extends BeanDeserializerModifier {
    
      @Override
      public JsonDeserializer<?> modifyMapDeserializer(DeserializationConfig config, MapType type, BeanDescription beanDesc, JsonDeserializer<?> deserializer {
    
        final JsonDeserializer<?> jsonDeserializer = super.modifyMapDeserializer(config, type, beanDesc, deserializer);
        if (type.getKeyType().isTypeOrSubTypeOf(String.class) && type.getContentType().isTypeOrSubTypeOf(String.class)) {
          return new MapCustomDeserializer();
        }
    
        return jsonDeserializer;
      }
    
    }
    
    static class MapCustomDeserializer extends JsonDeserializer<Map<String, String>> {
    
      @Override
      public Map<String, String> deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    
        final Map<String, String> map = jsonParser.readValueAs(Map.class);
    
        if (map != null) {
          map.replaceAll((key, value) -> Strings.nullToEmpty(value));
        }
        return map;
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-04
      • 2012-11-19
      • 2018-10-19
      • 1970-01-01
      • 2015-01-09
      • 1970-01-01
      • 1970-01-01
      • 2018-10-14
      相关资源
      最近更新 更多