我想将任意JSON反序列化为Map<String, Object>
。此地图的值可能是某些原始地图(例如Integer
,String
,LocalDate
,...)或其他Map<String, Object>
(递归)。
要获取原语,应为每个属性调用某种自定义客户端回调。根据密钥,将发生某些反序列化。例如(伪代码):
{
"name": "Bill",
"age": 53,
"timestamp": "2012-04-23T18:25:43.511Z",
"coordinates": "51.507351;-0.127758",
"address": {
"street": "Wallstreet",
"city": "NY"
}
}
Object convert(key, value) {
if ("name".equals(key)) {
return value.toString();
} else if ("timestamp".equals(key)) {
return LocalDate.parse(value);
} else if ("coordinates".equals(key)) {
return Coordinates.parse(value);
}
...
}
在SO Jackson - Recursive parsing into Map<String, Object>中,提供了一个简单的通用解决方案。但是,这只是将每个非对象属性反序列化为String
。是否可以向反序列化过程添加自定义客户端回调,如上所示?
答案 0 :(得分:0)
开箱即用:
class java.util.LinkedHashMap(
name -> class java.lang.String(Bill),
age -> class java.lang.Integer(53),
address -> class java.util.LinkedHashMap(
street -> class java.lang.String(Wallstreet),
city -> class java.lang.String(NY)
)
)
杰克逊将您示例中的输入转换为:
public class CustomMap extends LinkedHashMap<String, Object> {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private Object convertPrimitive(String key, Object value) {
switch (key) {
case "age":
return new BigInteger(value.toString());
case "city":
return value.toString().toLowerCase();
default:
return value;
}
}
private Object convertMap(String key, Object value) {
return OBJECT_MAPPER.convertValue(value, CustomMap.class);
}
@Override
public Object put(String key, Object value) {
return super.put(key, (value instanceof Map) ? convertMap(key, value) : convertPrimitive(key, value));
}
}
如果您想要一些自定义处理(例如,您想要BigInteger而不是年龄的整数),您可以使用自定义LinkedHashMap实现,例如:
new ObjectMapper.readValue("\"name\": ...", CustomMap.class);
这次,
class org.example.CustomMap(
name -> class java.lang.String(Bill),
age -> class java.math.BigInteger(53),
address -> class org.example.CustomMap(
street -> class java.lang.String(Wallstreet),
city -> class java.lang.String(ny)
)
)
将导致:
Variable Value
Chicken 5
Fish 3
Beef 2
Chicken 4
Beef 1
Fish 2