当尝试使用Map时,键被序列化为字符串,而值被正确地序列化为BigDecimal。这会在反序列化它时引起问题,因为它被反序列化为Map。
我需要将密钥序列化为BigDecimal而不是字符串,有什么方法可以做到吗?我正在使用Jackson-all-1.9.11.jar,但我也尝试使用jackson-2.12.4罐子,但同样的出现。
有什么解决办法吗?或者,我是否可以创建一个自定义序列化程序,它只覆盖ObjectMapper在BigDecimal键情况下自动使用的映射序列化程序?如果是,如何才能做到这一点?
下面是一个代码示例,包含返回的结果。
public static void main(String[] args)
{
try
{
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
Map<BigDecimal, BigDecimal> map = new HashMap<>();
map.put(BigDecimal.ONE, BigDecimal.ONE);
map.put(BigDecimal.TEN, BigDecimal.TEN);
String str = mapper.writeValueAsString(map);
System.out.println(str);
}
catch(Exception e)
{
e.printStackTrace();
}
}结果如下:
["java.util.HashMap",{"10":["java.math.BigDecimal",10],"1":["java.math.BigDecimal",1]}]发布于 2021-07-13 10:26:02
您需要为希望在Map中用作键的每个类实现一组自定义密钥序列化器和反序列化器。例如,对于数字,它可能如下所示:
class KeyBigDecimalJsonSerializer extends JsonSerializer<Number> {
@Override
public void serialize(Number value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeFieldName(value + "_" + value.getClass().getName());
}
}
class CustomKeyDeserializer extends KeyDeserializer {
private final ObjectMapper mapper = new ObjectMapper();
@Override
public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException {
if (key.contains("_")) {
return deserializeKeyWithClass(key, ctxt);
}
return key;
}
private Object deserializeKeyWithClass(String key, DeserializationContext ctxt) throws IOException {
String[] parts = key.split("_");
try {
Class<?> aClass = ctxt.findClass(parts[1]);
return mapper.readValue(parts[0], aClass);
} catch (ClassNotFoundException e) {
throw new IOException(e);
}
}
}用法:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
public class MapKeysApp {
public static void main(String[] args) throws Exception {
SimpleModule module = new SimpleModule();
module.addKeySerializer(Number.class, new KeyBigDecimalJsonSerializer());
module.addKeyDeserializer(Object.class, new CustomKeyDeserializer());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
Map<Object, Object> map = new HashMap<>();
map.put(BigDecimal.ONE, BigDecimal.ONE);
map.put(BigDecimal.TEN, BigDecimal.TEN);
map.put(2.1D, 2.1D);
map.put(100, 100);
map.put("TEN", "ten");
String json = mapper.writeValueAsString(map);
System.out.println(json);
mapper.readValue(json, Map.class).forEach((k, v) -> {
System.out.println(k + " (" + k.getClass().getName() + ") : " + v + " (" + v.getClass().getName() + ")");
});
}
}以上代码打印:
["java.util.HashMap",{"100_java.lang.Integer":100,"10_java.math.BigDecimal":["java.math.BigDecimal",10],"TEN":"ten","2.1_java.lang.Double":2.1,"1_java.math.BigDecimal":["java.math.BigDecimal",1]}]
100 (java.lang.Integer) : 100 (java.lang.Integer)
10 (java.math.BigDecimal) : 10 (java.math.BigDecimal)
TEN (java.lang.String) : ten (java.lang.String)
2.1 (java.lang.Double) : 2.1 (java.lang.Double)
1 (java.math.BigDecimal) : 1 (java.math.BigDecimal)https://stackoverflow.com/questions/68313450
复制相似问题