[英]Serializing map having value of different types to JSON using Jackson in Java
我想將給定的哈希映射序列化為 json 並將其反序列化回原始映射。
在這里,我想使這個通用,以便無論值的類型如何,它都可以無縫運行。
我使用以下代碼片段來構建地圖,然后將其作為 json 序列化:
Map<String, Map<String, Object>> argumentNameValueMap = new HashMap<>();
for (int i = 0; i < codeSignature.getParameterNames().length; i++) {
argumentNameValueMap.put(codeSignature.getParameterNames()[i],
mapper.convertValue(joinPoint.getArgs()[i],
Map.class)); <----THIS LINE IS FAILING WHEN ARGUMENT VALUE IS OF PRIMITIVE TYPE.
}
return mapper.writeValueAsString(argumentNameValueMap);
當要放入映射中的值的類型是一個對象但該值是任何原始類型(例如字符串/整數等)時失敗,這工作正常。
我可以通過編寫檢查關聯的值類型是否屬於任何原始類型並相應地添加 if else 來處理此問題。
但我想知道是否有更好的方法來做到這一點。 謝謝。
在JSON
規范中,公認的值是: JSON Object
- {...}
、 JSON Array
- [...]
、 string
、 number
、 false
、 true
和null
。 默認情況下,只有JSON Object
可以反序列化為Map
並且Map
可以序列化為JSON Object
。
在您的情況下,您需要手動處理其他類型並以某種方式將它們轉換為Map
實例。 您可以實現自己的com.fasterxml.jackson.databind.deser.DeserializationProblemHandler
,它允許在出現問題時攔截轉換機制。
您可以在下面找到一個簡單的實現方法:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
import com.fasterxml.jackson.databind.deser.ValueInstantiator;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class JsonApp {
public static void main(String[] args) {
Map<String, Object> source = new HashMap<>();
source.put("pojo", new SomeClass());
source.put("string", "String-Value");
source.put("int", 1);
source.put("null", null);
source.put("char", 'A');
source.put("long", Long.MIN_VALUE);
source.put("list", Arrays.asList(1, 3));
source.put("array", new int[]{12, 13});
ObjectMapper mapper = new ObjectMapper();
mapper.addHandler(new Convert2MapDeserializationProblemHandler());
Map<String, Map<String, Object>> argumentNameValueMap = new HashMap<>();
for (Map.Entry<String, Object> entry : source.entrySet()) {
argumentNameValueMap.put(entry.getKey(), mapper.convertValue(entry.getValue(), Map.class));
}
argumentNameValueMap.forEach((k, v) -> System.out.println(k + " -> " + v));
}
}
class Convert2MapDeserializationProblemHandler extends DeserializationProblemHandler {
@Override
public Object handleMissingInstantiator(DeserializationContext ctxt, Class<?> instClass, ValueInstantiator valueInsta, JsonParser p, String msg) throws IOException {
if (Map.class.isAssignableFrom(instClass)) {
Map<String, Object> map = new LinkedHashMap<>();
TreeNode value = p.readValueAsTree();
map.put("value", value);
return map;
}
return super.handleMissingInstantiator(ctxt, instClass, valueInsta, p, msg);
}
@Override
public Object handleUnexpectedToken(DeserializationContext ctxt, JavaType targetType, JsonToken t, JsonParser p, String failureMsg) throws IOException {
if (Map.class.isAssignableFrom(targetType.getRawClass())) {
Map<String, Object> map = new LinkedHashMap<>();
TreeNode value = p.readValueAsTree();
map.put("value", value);
return map;
}
return super.handleUnexpectedToken(ctxt, targetType, t, p, failureMsg);
}
}
class SomeClass {
String stringField = "Value!";
public String getStringField() {
return stringField;
}
public void setStringField(String stringField) {
this.stringField = stringField;
}
@Override
public String toString() {
return "SomeClass{" +
"stringField='" + stringField + '\'' +
'}';
}
}
上面的代碼打印:
pojo -> {stringField=Value!}
string -> {value="String-Value"}
null -> null
array -> {value=[12,13]}
char -> {value="A"}
list -> {value=[1,3]}
int -> {value=1}
long -> {value=-9223372036854775808}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.