Tôi biết đây là một câu hỏi khá cũ, nhưng tôi đã tìm kiếm một giải pháp để khử tuần tự hóa JSON chung cho một Map<String, Object>
, và không tìm thấy gì.
Cách trình giải nén yaml của tôi hoạt động, nó mặc định các đối tượng JSON là Map<String, Object>
khi bạn không chỉ định một loại, nhưng gson dường như không làm điều này. May mắn thay, bạn có thể hoàn thành nó với một trình giải nén tùy chỉnh.
Tôi đã sử dụng trình giải nén sau đây để khử lưu lượng tự nhiên bất cứ thứ gì, mặc định JsonObject
s thành Map<String, Object>
và JsonArray
s thành Object[]
s, trong đó tất cả các con đều được khử lưu tương tự.
private static class NaturalDeserializer implements JsonDeserializer<Object> {
public Object deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) {
if(json.isJsonNull()) return null;
else if(json.isJsonPrimitive()) return handlePrimitive(json.getAsJsonPrimitive());
else if(json.isJsonArray()) return handleArray(json.getAsJsonArray(), context);
else return handleObject(json.getAsJsonObject(), context);
}
private Object handlePrimitive(JsonPrimitive json) {
if(json.isBoolean())
return json.getAsBoolean();
else if(json.isString())
return json.getAsString();
else {
BigDecimal bigDec = json.getAsBigDecimal();
// Find out if it is an int type
try {
bigDec.toBigIntegerExact();
try { return bigDec.intValueExact(); }
catch(ArithmeticException e) {}
return bigDec.longValue();
} catch(ArithmeticException e) {}
// Just return it as a double
return bigDec.doubleValue();
}
}
private Object handleArray(JsonArray json, JsonDeserializationContext context) {
Object[] array = new Object[json.size()];
for(int i = 0; i < array.length; i++)
array[i] = context.deserialize(json.get(i), Object.class);
return array;
}
private Object handleObject(JsonObject json, JsonDeserializationContext context) {
Map<String, Object> map = new HashMap<String, Object>();
for(Map.Entry<String, JsonElement> entry : json.entrySet())
map.put(entry.getKey(), context.deserialize(entry.getValue(), Object.class));
return map;
}
}
Sự lộn xộn bên trong handlePrimitive
phương thức là để đảm bảo bạn chỉ nhận được Double hoặc Integer hoặc Long, và có thể tốt hơn, hoặc ít nhất là đơn giản hóa nếu bạn ổn với việc nhận BigDecimals, mà tôi tin là mặc định.
Bạn có thể đăng ký bộ chuyển đổi này như:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Object.class, new NaturalDeserializer());
Gson gson = gsonBuilder.create();
Và sau đó gọi nó như:
Object natural = gson.fromJson(source, Object.class);
Tôi không chắc tại sao đây không phải là hành vi mặc định trong gson, vì nó nằm trong hầu hết các thư viện tuần tự hóa bán cấu trúc khác ...
Map<String,Object> result = new Gson().fromJson(json, Map.class);
hoạt động với gson 2.6.2.