Konvertieren Sie Eigenschaftsnamen im JSON-Stil mit GSON in Java CamelCase-Namen

106

Ich verwende GSON , um JSON-Daten, die ich erhalte, in ein Java-Objekt zu konvertieren. Es funktioniert ziemlich gut in allen meinen Tests. Das Problem ist, dass unsere realen Objekte einige Eigenschaften wie is_online haben. GSON ordnet sie nur zu, wenn sie völlig gleich benannt sind. Es wäre schön, wenn GSON die Namen in den Java-Kamelfall isOnline konvertieren würde.

Es scheint, dass dies beim Erstellen der JSON-Daten möglich ist. Die Kamel-Groß- und Kleinschreibung wird in JSON in unterstrichene Wörter konvertiert. Aber ich kann keinen Weg finden, dies umgekehrt zu spezifizieren.

Janusz
quelle
5
Ich würde vorschlagen, eine Antwort zu akzeptieren
JeanValjean

Antworten:

313

Ich habe festgestellt, dass die folgende Einstellung perfekt funktioniert, wenn ich json mit unterstrichenen Attributen lese und in meinen Modellen Camelcasing verwende.

Gson gson = new GsonBuilder()
    .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
    .create()
Hampei
quelle
2
Tolle Antwort, danke! @janusz, wenn Ihnen eine dieser Antworten geholfen hat, markieren Sie sie bitte als Akzeptierte Antwort.
Sufinawaz
1
Wenn der Name zwei Unterstriche enthält, wird der erste Unterstrich ignoriert. Ex. this_key_has__two_underscores wird in thisKeyHas_TwoUnderscores konvertiert und umgekehrt. Der Schlüsselpunkt ist die FieldNamingPolicy, bei der die Aufzählung "Kleinbuchstaben" mit Unterstrichen sagt, während der konvertierte Name hier Großbuchstaben mit Unterstrichen (_T) hat.
Deepak GM
Sehr einfach, erspart mir das Kommentieren einiger Felder!
William T. Mallard
98

Sie können die SerializedNameAnmerkung verwenden:

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

Hinweis: Wenn Sie bereits eine festgelegt haben FieldNamingPolicy, SerializedNamewerden die Einstellungen für dieses bestimmte Feld überschrieben (sehr praktisch für Sonderfälle).

Saschoar
quelle
2

Denken Sie daran, dass Ihr Beispiel ein Randfall ist. Wenn Sie eine Eigenschaft 'foo' haben, sollte ihr Getter 'getFoo' heißen, und wenn Sie eine Eigenschaft namens 'foo_bar' haben, sollte ihr Getter 'getFooBar' heißen. In Ihrem Beispiel ordnen Sie jedoch einen Booleschen Wert und einen Booleschen Wert zu Namenskonventionen für Sonderfälle in Java. Eine primitive boolesche Eigenschaft mit dem Namen online sollte einen Getter mit dem Namen 'isOnline', NICHT 'getOnline' oder noch schlimmer 'getIsOnline' haben. Ein Boolesches Wrapper-Objekt (dh Boolesches Objekt) sollte diesem Sonderfall nicht folgen, und eine Eigenschaft mit dem Namen "online" sollte einen Getter mit dem Namen "getOnline" haben.

Daher ist es ein Randfall, boolesche Eigenschaften mit 'is' im Namen zu haben, bei denen Sie dieses bestimmte Präfix während Ihrer Konvertierung entfernen möchten. In umgekehrter Richtung möchte Ihr Code das json-Objekt möglicherweise sowohl auf einen rohen Eigenschaftsnamen als auch auf eine 'is_XXX'-Version untersuchen.

Jherico
quelle
2

Ich denke, was du willst, ist hier . Mithilfe von Anmerkungen können Sie GSON mitteilen, dass mySuperCoolField im JSON tatsächlich this_field_is_fun heißt und es korrekt entpackt. Zumindest denke ich, dass es auch für die Deserialisierung funktioniert.

Wenn dies nicht funktioniert, können Sie benutzerdefinierte JsonSerializer / JsonDeserializers verwenden, die hervorragend funktionieren. Sie müssen sie jedoch aktualisieren, um Änderungen in Ihrer Klasse vorzunehmen (z. B. wenn Sie ein Feld hinzufügen). Sie verlieren die Auto-Magie.

Am einfachsten (was hässlich, aber sehr sauber und einfach wäre, wenn der erste Vorschlag nicht funktioniert) wäre es, das Feld einfach so zu benennen, dass GSON glücklich wird, und zusätzliche Zugriffsmethoden mit den gewünschten Namen hinzuzufügen , z.B

public boolean isXXX() {return this.is_XXX;}
MBCook
quelle
Das Einfache ist, was ich gerade mache und es funktioniert einwandfrei. Der ganze hässliche, nicht typische Code im Java-Stil ist in den Datenklassen versteckt und wird von niemandem von außen gesehen. Aber es nervt mich immer noch ein bisschen :)
Janusz