Clase de datos Kotlin de Json usando GSON

105

Tengo una clase de Java POJO como esta:

class Topic {
    @SerializedName("id")
    long id;
    @SerializedName("name")
    String name;
}

y tengo una clase de datos de Kotlin como esta

 data class Topic(val id: Long, val name: String)

¿Cómo proporcionar json keya cualquier variable kotlin data classsimilar a la @SerializedNameanotación en las variables de Java?

erluxman
fuente
1
¿Cómo lo hiciste en Java? Muestre un ejemplo.
nhaarman
¿Qué es un selector json?
voddan
@voddan lo que quise decir con esos selectores json es que las cadenas que puedo usar para seleccionar un objeto / matriz json particular: en mi caso, "tema", "id", "imagen". Espero haberte dejado claro. Gracias :)
erluxman
@nhaarman He editado la pregunta, espero que eso sea lo que quieres decir
erluxman

Respuestas:

227

Clase de datos:

data class Topic(
  @SerializedName("id") val id: Long, 
  @SerializedName("name") val name: String, 
  @SerializedName("image") val image: String,
  @SerializedName("description") val description: String
)

a JSON:

val gson = Gson()
val json = gson.toJson(topic)

desde JSON:

val json = getJson()
val topic = gson.fromJson(json, Topic::class.java)
Anton Holovin
fuente
36
Use anotaciones solo cuando haya una discrepancia en el nombre de la variable. De lo contrario, sí, no es necesario
Vik
3
En mi opinión, las anotaciones nos permiten tener clases que al ser serializadas se pueden excluir o incluir las variables. Muy útil cuando se usa con modernización. Esto no envía basura al servidor. Además, cuando hay cambios en los nombres de las variables en el lado del servidor, es más doloroso cambiarlo directamente en la variable de clase que en la anotación.
Deneb Chorny
11
@Vik, una cosa a tener en cuenta es que los nombres de sus variables posiblemente se pueden ofuscar (como en una aplicación de Android), pero la anotación se dejará intacta
Caleb_Allen
@AntonGolovin No puedo pasar mi clase de datos desde el método Json. ¿Necesito declarar mi clase de datos dentro del archivo java?
Ravi Yadav
Si hace esto, creo que perderá el formato JSON que puede causar IllegalStateException en el futuro
portfoliobuilder
19

Basado en la respuesta de Anton Golovin

Detalles

  • Versión de Gson: 2.8.5
  • Android Studio 3.1.4
  • Versión de Kotlin: 1.2.60

Solución

Cree cualquier dato de clase y herede la interfaz JSONConvertable

interface JSONConvertable {
     fun toJSON(): String = Gson().toJson(this)
}

inline fun <reified T: JSONConvertable> String.toObject(): T = Gson().fromJson(this, T::class.java)

Uso

Clase de datos

data class User(
    @SerializedName("id") val id: Int,
    @SerializedName("email") val email: String,
    @SerializedName("authentication_token") val authenticationToken: String) : JSONConvertable

De JSON

val json = "..."
val object = json.toObject<User>()

A JSON

val json = object.toJSON()
Vasily Bodnarchuk
fuente
¿Por qué usas la SerializedNameanotación en lugar de la estrategia de nomenclatura de campos, Vasily?
peterchaula
2
@Peter porque @SerializedNameme permitirá usar nombres personalizados de las variables que pueden no coincidir con la clave json. Y sí, no puede usarlo @SerializedNamesi no lo necesita.
Vasily Bodnarchuk
2

Puedes usar similar en la clase Kotlin

class InventoryMoveRequest {
    @SerializedName("userEntryStartDate")
    @Expose
    var userEntryStartDate: String? = null
    @SerializedName("userEntryEndDate")
    @Expose
    var userEntryEndDate: String? = null
    @SerializedName("location")
    @Expose
    var location: Location? = null
    @SerializedName("containers")
    @Expose
    var containers: Containers? = null
}

Y también para la clase anidada, puede usar lo mismo como si hubiera un objeto anidado. Simplemente proporcione el nombre de serialización para la clase.

@Entity(tableName = "location")
class Location {

    @SerializedName("rows")
    var rows: List<Row>? = null
    @SerializedName("totalRows")
    var totalRows: Long? = null

}

por lo tanto, si recibe una respuesta del servidor, cada clave se asignará con JOSN.

Alos, convierta la lista a JSON:

val gson = Gson()
val json = gson.toJson(topic)

ndroid convierte de JSON a Object:

val json = getJson()
val topic = gson.fromJson(json, Topic::class.java)
Pawan Soni
fuente