Je sais qu'il s'agit d'une question assez ancienne, mais je cherchais une solution pour désérialiser de manière générique des JSON imbriqués dans un fichier de type Map<String, Object>
et n'a rien trouvé.
La façon dont mon désérialiseur yaml fonctionne, il donne par défaut aux objets JSON la valeur suivante Map<String, Object>
lorsque vous ne spécifiez pas de type, mais gson ne semble pas le faire. Heureusement, vous pouvez le faire avec un désérialiseur personnalisé.
J'ai utilisé le désérialiseur suivant pour désérialiser naturellement n'importe quoi, par défaut JsonObject
s à Map<String, Object>
y JsonArray
s à Object[]
s, où tous les enfants sont désérialisés de la même manière.
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;
}
}
Le désordre à l'intérieur de la handlePrimitive
permet de s'assurer que vous n'obtenez jamais qu'un Double, un Integer ou un Long, et pourrait probablement être améliorée, ou du moins simplifiée si vous êtes d'accord pour obtenir des BigDecimals, ce qui est, je crois, la valeur par défaut.
Vous pouvez enregistrer cet adaptateur comme :
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Object.class, new NaturalDeserializer());
Gson gson = gsonBuilder.create();
Et ensuite l'appeler comme ça :
Object natural = gson.fromJson(source, Object.class);
Je ne sais pas pourquoi ce n'est pas le comportement par défaut dans gson, puisque c'est le cas dans la plupart des autres bibliothèques de sérialisation semi-structurée...
28 votes
Map<String,Object> result = new Gson().fromJson(json, Map.class);
fonctionne avec gson 2.6.2.1 votes
Comment se reconvertir ? Je veux dire de Map à Json Array.