Konwertuj nazwy właściwości stylu JSON na nazwy Java CamelCase za pomocą GSON

107

Używam GSON do konwersji danych JSON, które otrzymuję, na obiekt Java. Działa całkiem dobrze we wszystkich moich testach. Problem polega na tym, że nasze rzeczywiste obiekty mają pewne właściwości, takie jak is_online. GSON odwzorowuje je tylko wtedy, gdy są nazwane całkowicie równymi, byłoby miło, gdyby GSON przekonwertował te nazwy do formatu Java wielbłąda isOnline.

Wydaje się, że jest to możliwe podczas tworzenia danych JSON, wielkość wielbłąda jest konwertowana na podkreślone słowa oddzielone w JSON. Ale nie mogę znaleźć sposobu, aby określić to na odwrót.

Janusz
źródło
5
Proponuję przyjąć odpowiedź
JeanValjean

Odpowiedzi:

313

Zauważyłem, że poniższe ustawienie działa idealnie podczas czytania json z podkreślonymi atrybutami i używania camelcasing w moich modelach.

Gson gson = new GsonBuilder()
    .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
    .create()
Hampei
źródło
2
Świetna odpowiedź, dziękuję! @janusz, jeśli którakolwiek z tych odpowiedzi Ci pomogła, oznacz je jako zaakceptowaną odpowiedź.
sufinawaz
1
Jeśli masz przypadek, w którym nazwa zawiera dwa podkreślenia, ignoruje pierwszy podkreślenie. Dawny. this_key_has__two_underscores zostanie przekonwertowane na thisKeyHas_TwoUnderscores i to samo odwrotnie. Kluczowym punktem jest FieldNamingPolicy, w którym wyliczenie mówi „małe litery” z podkreśleniami, podczas gdy tutaj przekonwertowana nazwa ma wielką literę z podkreśleniem (_T).
Deepak GM
Bardzo proste, dzięki czemu nie muszę dodawać adnotacji do kilku pól!
William T. Mallard
99

Możesz użyć SerializedNameadnotacji:

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

Uwaga: jeśli już ustawiłeś FieldNamingPolicy, SerializedNamenadpisze swoje ustawienia dla tego konkretnego pola (bardzo przydatne w specjalnych przypadkach).

saschoar
źródło
2

Pamiętaj, że twój przykład to skrajna sprawa. Jeśli masz właściwość „foo”, jej metoda pobierająca powinna mieć nazwę „getFoo”, a jeśli masz właściwość „foo_bar”, jej metoda pobierająca powinna mieć nazwę „getFooBar”, jednakże w naszym przykładzie mapujesz wartość logiczną, a wartości logiczne mają specjalne konwencje nazewnictwa przypadków w java. Prymitywna właściwość logiczna o nazwie online powinna mieć metodę pobierającą o nazwie „isOnline”, NIE „getOnline” lub, co gorsza, „getIsOnline”. Boolowski obiekt opakowujący (np. Boolean) nie powinien być zgodny z tym specjalnym przypadkiem, a właściwość o nazwie „online” powinna mieć element pobierający o nazwie „getOnline”.

Dlatego posiadanie właściwości logicznych z „jest” w nazwie jest przypadkiem skrajnym, w którym będziesz chciał usunąć ten konkretny prefiks podczas konwersji. W odwrotnym kierunku kod może chcieć sprawdzić obiekt json zarówno pod kątem surowej nazwy właściwości, jak i wersji „is_XXX”.

Jherico
źródło
2

Myślę, że to, czego chcesz, jest tutaj . Używając adnotacji, możesz powiedzieć GSON, że mySuperCoolField w rzeczywistości nazywa się this_field_is_fun w JSON i rozpakuje go poprawnie. Przynajmniej myślę, że działa również w przypadku deserializacji.

Jeśli to nie zadziała, możesz użyć niestandardowych JsonSerializer / JsonDeserializers, które działają świetnie, ale musisz je zaktualizować pod kątem zmian w swojej klasie (na przykład podczas dodawania pola). Tracisz auto-magię.

Najłatwiejszą rzeczą do zrobienia (co byłoby brzydkie, ale bardzo przejrzyste i proste, gdyby pierwsza sugestia nie zadziałała) byłoby po prostu nazwanie pola w taki sposób, aby zadowolić GSON, i dodanie dodatkowych metod pomocniczych z nazwami, które lubisz , np

public boolean isXXX() {return this.is_XXX;}
MBCook
źródło
Najłatwiej jest to, co robię w tej chwili i działa dobrze. Cały brzydki, nietypowy kod w stylu Java jest ukryty w klasach danych i nikt z zewnątrz go nie zobaczy. Ale nadal trochę mnie to dręczy :)
Janusz