Comment conserver la séquence des champs dans la sérialisation de Gson

Il semble que Gson.toJson (object Object) génère du code JSON avec des champs répartis de manière aléatoire sur l’object. Est-il possible de corriger l’ordre des champs d’une manière ou d’une autre?

public class Foo { public Ssortingng bar; public Ssortingng baz; public Foo( Ssortingng bar, Ssortingng baz ) { this.bar = bar; this.baz = baz; } } Gson gson = new Gson(); Ssortingng jsonRequest = gson.toJson(new Foo("bar","baz")); // jsonRequest now can be { "bar":"bar", "baz":"baz" } (which is correct) // and can be { "baz":"baz", "bar":"bar" } (which is a wrong sequence) 

Merci.

Si GSON ne prend pas en charge la définition de l’ordre des champs, d’autres bibliothèques le font. Jackson permet de définir cela avec @JsonPropertyOrder, par exemple. Avoir à spécifier son propre sérialiseur personnalisé semble être un travail énorme pour moi.

Et oui, je suis d’accord que selon la spécification JSON, l’application ne devrait pas s’attendre à un classement spécifique des champs.

Vous devez créer un sérialiseur JSON personnalisé.

Par exemple

 public class FooJsonSerializer implements JsonSerializer { @Override public JsonElement serialize(Foo foo, Type type, JsonSerializationContext context) { JsonObject object = new JsonObject(); object.add("bar", context.serialize(foo.getBar()); object.add("baz", context.serialize(foo.getBaz()); // ... return object; } } 

et l’utiliser comme suit:

 Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class, new FooJsonSerializer()).create(); Ssortingng json = gson.toJson(foo); // ... 

Cela préserve l’ordre tel que vous l’avez spécifié dans le sérialiseur.

Voir également:

  • Gson User Guide – Des sérialiseurs et des désérialiseurs personnalisés

Voici ma solution pour lire en boucle les fichiers texte json dans un répertoire donné et écrire par dessus les versions sortingées:

 private void standardizeFormat(File dir) throws IOException { File[] directoryListing = dir.listFiles(); if (directoryListing != null) { for (File child : directoryListing) { Ssortingng path = child.getPath(); JsonReader jsonReader = new JsonReader(new FileReader(path)); Gson gson = new GsonBuilder().setPrettyPrinting().registerTypeAdapter(LinkedTreeMap.class, new SortedJsonSerializer()).create(); Object data = gson.fromJson(jsonReader, Object.class); JsonWriter jsonWriter = new JsonWriter(new FileWriter(path)); jsonWriter.setIndent(" "); gson.toJson(data, Object.class, jsonWriter); jsonWriter.close(); } } } private class SortedJsonSerializer implements JsonSerializer { @Override public JsonElement serialize(LinkedTreeMap foo, Type type, JsonSerializationContext context) { JsonObject object = new JsonObject(); TreeSet sorted = Sets.newTreeSet(foo.keySet()); for (Object key : sorted) { object.add((Ssortingng) key, context.serialize(foo.get(key))); } return object; } } 

C’est plutôt pirate car cela dépend du fait que Gson utilise LinkedTreeMap lorsque le Type est simplement Object. Ceci est un détail d’implémentation qui n’est probablement pas garanti. En tout cas, c’est suffisant pour mes fins de courte durée …