Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin object deserialization with GSON

Tags:

gson

kotlin

I have a class

class ThreadComment(
    banned: Int,
    closed: Int,
    comment: String?,
    date: String?,
    email: String?,
    files: ArrayList<File>?,
    lasthit: Int,
    name: String?,
    num: String?,
    op: Int,
    parent: String?,
    postsCount: Int,
    sticky: Int,
    subject: String?,
    tags: String?,
    timestamp: Int,
    trip: String?) : Comment(banned, closed, comment, date, email, files, lasthit, name, num, op, parent, postsCount, sticky, subject, tags, timestamp, trip) {

val answers: ArrayList<String> = ArrayList()}

Parent class looks like

open class Comment(
    @com.google.gson.annotations.SerializedName("banned")
    val banned: Int = 0,

    @com.google.gson.annotations.SerializedName("closed")
    val closed: Int = 0,

    @com.google.gson.annotations.SerializedName("comment")
    val comment: String? = null,

    @com.google.gson.annotations.SerializedName("date")
    val date: String? = null,

    @com.google.gson.annotations.SerializedName("email")
    val email: String? = null,

    @com.google.gson.annotations.SerializedName("files")
    val files: ArrayList<File>? = null,

    @com.google.gson.annotations.SerializedName("lasthit")
    val lasthit: Int = 0,

    @com.google.gson.annotations.SerializedName("name")
    val name: String? = null,

    @com.google.gson.annotations.SerializedName("num")
    val num: String? = null,

    @com.google.gson.annotations.SerializedName("op")
    val op: Int = 0,

    @com.google.gson.annotations.SerializedName("parent")
    val parent: String? = null,

    @com.google.gson.annotations.SerializedName("posts_count")
    val postsCount: Int = 0,

    @com.google.gson.annotations.SerializedName("sticky")
    val sticky: Int = 0,

    @com.google.gson.annotations.SerializedName("subject")
    val subject: String? = null,

    @com.google.gson.annotations.SerializedName("tags")
    val tags: String? = null,

    @com.google.gson.annotations.SerializedName("timestamp")
    val timestamp: Int = 0,

    @com.google.gson.annotations.SerializedName("trip")
    val trip: String? = null) : Serializable

But after deserialization with GSON answers field is null. Debugger

I also tried to put initiation into init{}, but it still null, by lazy throws an exception about calling lazy.getValue on a null object reference

like image 630
Ufkoku Avatar asked Sep 29 '16 21:09

Ufkoku


2 Answers

That´s weird, I just used @SerializedName normally as in Java with a data class and it worked:

data class(@SerializedName("my_string_value") val myStringValue: String, @SerializedName("my_int_value") val myIntValue: Int)
like image 73
Jesus Almaral - Hackaprende Avatar answered Sep 27 '22 21:09

Jesus Almaral - Hackaprende


As described in this answer Gson can unsafely handle no-args constructor scenarios. It does so by leveraging UnsafeAllocator that in turn uses allocateInstanсe(Class p). This means that when there is no no-args constructor and there is no custom instance creator registered the object created by Gson will have fields initialized with their declared types default values.

To resolve that either add a no-arg constructor i.e

private constructor() : this(-1, -1, "", "", "", null, -1, "", "", -1, null, -1, -1, null, null, -1, null)

Or add default parameter values to your primary constructor like so:

class ThreadComment(
        banned: Int = -1,
        closed: Int = -1,
        comment: String? = null,
        date: String? = null,
        email: String? = null,
        files: ArrayList<File>? = null,
        lasthit: Int = -1,
        name: String? = null,
        num: String? = null,
        op: Int = -1,
        parent: String? = null,
        postsCount: Int = -1,
        sticky: Int = -1,
        subject: String? = null,
        tags: String? = null,
        timestamp: Int = -1,
        trip: String? = null
) : Comment(banned, closed, comment, date, email, files, lasthit, name, num, op, parent, postsCount, sticky, subject, tags, timestamp, trip) {
    val answers: ArrayList<String> = ArrayList()
}
like image 22
miensol Avatar answered Sep 27 '22 20:09

miensol