Convertir les noms de propriétés de style JSON en noms Java CamelCase avec GSON

107

J'utilise GSON pour convertir les données JSON que j'obtiens en un objet Java. Cela fonctionne plutôt bien dans tous mes tests. Le problème est que nos objets réels ont des propriétés nommées comme is_online. GSON ne les mappe que s'ils sont nommés totalement égaux, ce serait bien que GSON convertisse les noms en Java camel case isOnline.

Il semble que cela soit possible lors de la création des données JSON, la casse du camel est convertie en mots séparés par soulignement dans JSON. Mais je ne peux pas trouver un moyen de spécifier cela dans l'autre sens.

Janusz
la source
5
Je propose d'accepter une réponse
JeanValjean

Réponses:

313

J'ai trouvé que le paramètre suivant fonctionne parfaitement lors de la lecture de json avec des attributs soulignés et de l'utilisation du camelcasing dans mes modèles.

Gson gson = new GsonBuilder()
    .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
    .create()
Hampei
la source
2
Excellente réponse, merci! @janusz, si l'une de ces réponses vous a aidé, veuillez la marquer comme réponse acceptée.
sufinawaz
1
Si vous avez un cas où le nom contient deux traits de soulignement, il ignore le premier trait de soulignement. Ex. this_key_has__two_underscores sera converti en thisKeyHas_TwoUnderscores et le même vice versa. Le point clé est le FieldNamingPolicy où l'énumération dit "minuscule" avec des traits de soulignement alors qu'ici le nom converti a une majuscule avec un trait de soulignement (_T).
Deepak GM
Très simple, cela m'évite d'avoir à annoter un tas de champs!
William T.Mallard
99

Vous pouvez utiliser l' SerializedNameannotation:

@SerializedName("field_name_in_json")
private final String fieldNameInJava;

Remarque: lorsque vous avez FieldNamingPolicydéjà défini un , SerializedNameremplacera ses paramètres pour ce champ spécifique (très pratique pour des cas particuliers).

saschoar
la source
2

Gardez à l'esprit que votre exemple est un cas extrême. Si vous avez une propriété 'foo', son getter doit être nommé 'getFoo', et si vous avez une propriété nommée 'foo_bar', son getter doit être nommé 'getFooBar', cependant, dans votre exemple, vous mappez un booléen et les booléens ont conventions de dénomination des cas spéciaux en java. Une propriété booléenne primitive nommée online devrait avoir un getter nommé 'isOnline', PAS 'getOnline' ou pire encore, 'getIsOnline'. Un objet wrapper booléen (c'est-à-dire Boolean) ne doit pas suivre ce cas particulier et une propriété nommée «online» doit avoir un getter nommé «getOnline».

Par conséquent, avoir des propriétés booléennes avec «est» dans le nom est un cas de bord, où vous voudrez supprimer ce préfixe particulier lors de votre conversion. Dans le sens inverse, votre code peut souhaiter inspecter l'objet json à la fois pour un nom de propriété brut et pour une version 'is_XXX'.

Jherico
la source
2

Je pense que ce que tu veux est ici . En utilisant des annotations, vous pouvez dire à GSON que mySuperCoolField est en fait appelé this_field_is_fun dans le JSON et qu'il le décompressera correctement. Au moins, je pense que cela fonctionne aussi pour la désérialisation.

Si cela ne fonctionne pas, vous pouvez utiliser des JsonSerializer / JsonDeserializers personnalisés, qui fonctionnent très bien, mais vous devez les mettre à jour pour les changements dans votre classe (comme lorsque vous ajoutez un champ). Vous perdez l'auto-magie.

La chose la plus simple à faire (ce qui serait moche, mais très propre et simple si la première suggestion ne fonctionne pas) serait simplement de nommer le champ de manière à rendre GSON heureux, et d'ajouter des méthodes d'accesseur supplémentaires avec les noms que vous aimez , par exemple

public boolean isXXX() {return this.is_XXX;}
MBCook
la source
la chose facile est ce que je fais en ce moment et cela fonctionne très bien. Tout le code de style java laid et non typique est caché dans les classes de données et personne de l'extérieur ne le verra. Mais ça me harcèle encore un peu :)
Janusz