web-dev-qa-db-fra.com

Gson: Existe-t-il un moyen plus simple de sérialiser une carte?

Ce le lien du projet Gson semble indiquer que je devrais procéder de la manière suivante pour la sérialisation d'une carte typée JSON:

    public static class NumberTypeAdapter 
      implements JsonSerializer<Number>, JsonDeserializer<Number>,
InstanceCreator<Number> {

    public JsonElement serialize(Number src, Type typeOfSrc, JsonSerializationContext
context) {
      return new JsonPrimitive(src);
    }

    public Number deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context)
        throws JsonParseException {
      JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive();
      if (jsonPrimitive.isNumber()) {
        return jsonPrimitive.getAsNumber();
      } else {
        throw new IllegalStateException("Expected a number field, but was " + json);
      }
    }

    public Number createInstance(Type type) {
      return 1L;
    }
  }

  public static void main(String[] args) {
    Map<String, Number> map = new HashMap<String, Number>();    
    map.put("int", 123);
    map.put("long", 1234567890123456789L);
    map.put("double", 1234.5678D);
    map.put("float", 1.2345F);
    Type mapType = new TypeToken<Map<String, Number>>() {}.getType();

    Gson gson = new GsonBuilder().registerTypeAdapter(Number.class, new
NumberTypeAdapter()).create();
    String json = gson.toJson(map, mapType);
    System.out.println(json);

    Map<String, Number> deserializedMap = gson.fromJson(json, mapType);
    System.out.println(deserializedMap);
  }

Cool et ça marche, mais on dirait beaucoup de frais généraux ( toute une classe de type Adapter Adapter?). J'ai utilisé d'autres bibliothèques JSON telles que JSONLib et elles vous permettent de créer une carte de la manière suivante:

JSONObject json = new JSONObject();
for(Entry<String,Integer> entry : map.entrySet()){
     json.put(entry.getKey(), entry.getValue());
}

Ou si j'ai une classe personnalisée, quelque chose comme ce qui suit:

JSONObject json = new JSONObject();
for(Entry<String,MyClass> entry : map.entrySet()){
 JSONObject myClassJson =  JSONObject.fromObject(entry.getValue());
     json.put(entry.getKey(), myClassJson);
}

Le processus est plus manuel, mais nécessite beaucoup moins de code et ne nécessite pas de temps supplémentaire pour créer un adaptateur de type personnalisé pour Number ou dans la plupart des cas pour ma propre classe personnalisée .

Est-ce le seul moyen de sérialiser une carte avec Gson, ou quelqu'un a-t-il trouvé un moyen de dépasser les recommandations de Gson dans le lien ci-dessus.

56
stevebot

Seule la partie TypeToken est nécessaire (lorsqu'il y a des génériques impliqués).

Map<String, String> myMap = new HashMap<String, String>();
myMap.put("one", "hello");
myMap.put("two", "world");

Gson gson = new GsonBuilder().create();
String json = gson.toJson(myMap);

System.out.println(json);

Type typeOfHashMap = new TypeToken<Map<String, String>>() { }.getType();
Map<String, String> newMap = gson.fromJson(json, typeOfHashMap); // This type must match TypeToken
System.out.println(newMap.get("one"));
System.out.println(newMap.get("two"));

Sortie:

{"two":"world","one":"hello"}
hello
world
116
arturo

Default

L'implémentation Gson par défaut de la sérialisation Map utilise toString() sur la clé:

Gson gson = new GsonBuilder()
        .setPrettyPrinting().create();
Map<Point, String> original = new HashMap<>();
original.put(new Point(1, 2), "a");
original.put(new Point(3, 4), "b");
System.out.println(gson.toJson(original));

Va donner:

{
  "Java.awt.Point[x\u003d1,y\u003d2]": "a",
  "Java.awt.Point[x\u003d3,y\u003d4]": "b"
}

Utiliser enableComplexMapKeySerialization

Si vous souhaitez que la clé de carte soit sérialisée conformément aux règles Gson par défaut, vous pouvez utiliser enableComplexMapKeySerialization . Cela retournera un tableau de tableaux de paires clé-valeur:

Gson gson = new GsonBuilder().enableComplexMapKeySerialization()
        .setPrettyPrinting().create();
Map<Point, String> original = new HashMap<>();
original.put(new Point(1, 2), "a");
original.put(new Point(3, 4), "b");
System.out.println(gson.toJson(original));

Reviendra:

[
  [
    {
      "x": 1,
      "y": 2
    },
    "a"
  ],
  [
    {
      "x": 3,
      "y": 4
    },
    "b"
  ]
]

Plus de détails peuvent être trouvés ici .

86
matt burns

Je suis à peu près sûr que GSON sérialise/désérialise les cartes et plusieurs cartes imbriquées (c'est-à-dire Map<String, Map<String, Object>>) très bien par défaut. Je pense que l’exemple fourni n’est rien de plus qu’un point de départ si vous devez faire quelque chose de plus complexe.

Consultez la classe MapTypeAdapterFactory dans le code source GSON: http://code.google.com/p/google-gson/source/browse/trunk/gson/src/main/Java/com/google/gson/ internal/bind/MapTypeAdapterFactory.Java

Tant que les types de clés et de valeurs peuvent être sérialisés en chaînes JSON (et que vous pouvez créer vos propres sérialiseurs/désérialiseurs pour ces objets personnalisés), vous ne devriez pas rencontrer de problèmes.

4
Ankit Aggarwal

Dans Gson 2.7.2, c'est aussi simple que

Gson gson = new Gson();
String serialized = gson.toJson(map);
3
isapir