148

I have Java POJO class like this:

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

and I have a Kotlin data class Like this

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

How to provide the json key to any variables of the kotlin data class like the @SerializedName annotation in java variables ?

erluxman
  • 18,155
  • 20
  • 92
  • 126

3 Answers3

296

Data class:

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

to JSON:

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

from JSON:

val json = getJson()
val topic = gson.fromJson(json, Topic::class.java)
Isaac Khor
  • 115
  • 1
  • 2
  • 6
Anton Holovin
  • 5,513
  • 1
  • 31
  • 33
  • 59
    Use annotations only when there's a variable name mismatch. Otherwise, yeah, not needed – Vik Sep 29 '17 at 22:35
  • 5
    In my opinion, the annotations allow us to have classes that when serialized can be excluded or include the variables. Very useful when used with retrofit. This does not send garbage to the server. Also, when there are changes in the names of the variables on the server side, it is more painful to change it directly in the class variable than in the annotation. – Deneb Chorny Nov 14 '17 at 17:11
  • 25
    @Vik one thing to note is your variable names can possibly be obfuscated (like in an Android app) but the annotation will be left intact – Caleb_Allen Jan 11 '18 at 22:06
  • @AntonGolovin I am not able to pass my data class in from Json method.Do I need to declare my data class inside java file? – Ravi Yadav Feb 20 '18 at 06:56
  • If you do this, I believe you will lost JSON format which may cause IllegalStateException down the road – portfoliobuilder Jul 22 '19 at 22:12
26

Based on answer of Anton Golovin

Details

  • Gson version: 2.8.5
  • Android Studio 3.1.4
  • Kotlin version: 1.2.60

Solution

Create any class data and inherit JSONConvertable interface

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

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

Usage

Data class

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

From JSON

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

To JSON

val json = object.toJSON()
Vasily Bodnarchuk
  • 24,482
  • 9
  • 132
  • 127
  • Why do you use the `SerializedName` annotation instead of the field naming strategy, Vasily? – Peter Chaula Aug 22 '19 at 17:34
  • 3
    @Peter because `@SerializedName` will allow me to use custom names of the variables which may not match with json key. And yes, you may not use `@SerializedName` if you do not need it. – Vasily Bodnarchuk Aug 22 '19 at 17:40
4

You can use similar in Kotlin class

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
}

And also for nested class you can use same like if there is nested object. Just provide Serialize name for the Class.

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

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

}

so if get response from the server each key will map with JOSN.

Alos, convert List to JSON:

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

ndroid convert from JSON to Object:

val json = getJson()
val topic = gson.fromJson(json, Topic::class.java)
Pawan Soni
  • 860
  • 8
  • 19