我正试图为所有jsonMap<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但我希望它适用于所有地图。
我也尝试过调整这个解决方案来进行反序列化,但它抛出了NullPointerException
更新:"null到empty"的转换需要仅在映射(具有字符串值(上工作。(参见上面的更新示例(
看,它对我有用:
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;
}
}
我最终使用了如下的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;
}
}