Convierta nombres de propiedades de estilo JSON a nombres Java CamelCase con GSON

106

Estoy usando GSON para convertir datos JSON que obtengo en un objeto Java. Funciona bastante bien en todas mis pruebas. El problema es que nuestros objetos reales tienen algunas propiedades denominadas como is_online. GSON solo los mapea si tienen el mismo nombre, sería bueno que GSON convierta los nombres a Java camel case isOnline.

Parece que esto es posible al crear los datos JSON, el caso de camello se convierte en guiones bajos separados en JSON. Pero no puedo encontrar una manera de especificar esto al revés.

Janusz
fuente
5
Propongo aceptar una respuesta
JeanValjean

Respuestas:

313

He encontrado que la siguiente configuración funciona perfectamente al leer json con atributos subrayados y usar camelcasing en mis modelos.

Gson gson = new GsonBuilder()
    .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
    .create()
Hampei
fuente
2
¡Gran respuesta, gracias! @janusz, si alguna de estas respuestas le ayudó, márquelas como Respuesta Aceptada.
sufinawaz
1
Si tiene un caso en el que el nombre contiene dos guiones bajos, ignora el primer guión bajo. Ex. this_key_has__two_underscores se convertirá en thisKeyHas_TwoUnderscores y lo mismo viceversa. El punto clave es FieldNamingPolicy donde la enumeración dice "minúscula" con guiones bajos, mientras que aquí el nombre convertido tiene una mayúscula con guión bajo (_T).
Deepak GM
Muy simple, ¡me ahorra tener que anotar un montón de campos!
William T. Mallard
98

Puede utilizar la SerializedNameanotación:

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

Nota: Cuando ya haya configurado un FieldNamingPolicy, SerializedNamesobrescribirá su configuración para ese campo específico (bastante útil para casos especiales).

Saschoar
fuente
2

Tenga en cuenta que su ejemplo es un caso marginal. Si tiene una propiedad 'foo', su captador debería llamarse 'getFoo', y si tiene una propiedad llamada 'foo_bar', su captador debería llamarse 'getFooBar', sin embargo, en su ejemplo está mapeando un booleano y los booleanos tienen convenciones de nomenclatura de casos especiales en java. Una propiedad booleana primitiva llamada online debería tener un getter llamado 'isOnline', NO 'getOnline' o peor aún, 'getIsOnline'. Un objeto contenedor booleano (es decir, booleano) no debería seguir este caso especial y una propiedad llamada 'online' debería tener un getter llamado 'getOnline'.

Por lo tanto, tener propiedades booleanas con 'es' en el nombre es un caso límite, donde querrá eliminar este prefijo particular durante su conversión. En la dirección inversa, es posible que su código desee inspeccionar el objeto json en busca de un nombre de propiedad sin formato y una versión 'is_XXX'.

Jherico
fuente
2

Creo que lo que quieres está aquí . Usando anotaciones, puede decirle a GSON que mySuperCoolField en realidad se llama this_field_is_fun en el JSON y lo descomprimirá correctamente. Al menos creo que también funciona para la deserialización.

Si eso no funciona, puede usar JsonSerializer / JsonDeserializers personalizados, que funcionan muy bien, pero debe actualizarlos para los cambios en su clase (como cuando agrega un campo). Pierdes la magia automática.

Lo más fácil de hacer (lo cual sería feo, pero muy limpio y simple si la primera sugerencia no funciona) sería simplemente nombrar el campo de una manera que haga feliz a GSON y agregar métodos de acceso adicionales con los nombres que desee. , p.ej

public boolean isXXX() {return this.is_XXX;}
MBCook
fuente
lo fácil es lo que estoy haciendo en este momento y funciona bien. Todo el código de estilo java feo y no típico está oculto en las clases de datos y nadie de fuera lo verá. Pero todavía me molesta un poco :)
Janusz