Kotlin数据类使用GSON动态创建其字段的json

时间:2018-11-27 13:10:32

标签: serialization kotlin constructor android gson

我有一个像这样的数据类:

data class TestModel(
     val id: Int, 
     val description: String, 
     val picture: String)

如果我使用GSON从此数据类创建JSON,并生成类似这样的结果

{"id":1,"description":"Test", "picture": "picturePath"}

如果我需要数据类中的以下JSON,该怎么办:

{"id":1, "description":"Test"}

其他时间:

`{"id":1, "picture": "picturePath"}

` 预先感谢!

3 个答案:

答案 0 :(得分:2)

您可以通过编写自定义适配器和可选类型来解决此问题:

import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter

data class TestModel(
    val id: Int,
    val description: String? = "",
    val picture: String? = "")

class TesModelTypeAdapter : TypeAdapter<TestModel>() {
    override fun read(reader: JsonReader?): TestModel {
        var id: Int? = null
        var picture: String? = null
        var description: String? = null

        reader?.beginObject()
        while (reader?.hasNext() == true) {
            val name = reader.nextName()

            if (reader.peek() == JsonToken.NULL) {
                reader.nextNull()
                continue
            }

            when (name) {
                "id" -> id = reader.nextInt()
                "picture" -> picture = reader.nextString()
                "description" -> description = reader.nextString()
            }
        }
        reader?.endObject()

        return when {
            !picture.isNullOrBlank() && description.isNullOrBlank() -> TestModel(id = id ?: 0, picture = picture)
            !description.isNullOrBlank() && picture.isNullOrBlank() -> TestModel(id = id ?: 0, description = description)
            else -> TestModel(id ?: 0, picture, description)
        }
    }

    override fun write(out: JsonWriter?, value: TestModel?) {
        out?.apply {
            beginObject()

            value?.let {
                when {
                    !it.picture.isNullOrBlank() && it.description.isNullOrBlank() -> {
                        name("id").value(it.id)
                    name("picture").value(it.picture)
                    }
                    !it.description.isNullOrBlank() && it.picture.isNullOrBlank() -> {
                        name("id").value(it.id)
                    name("description").value(it.description)
                    }
                    else -> {
                        name("id").value(it.id)
                        name("picture").value(it.picture)
                    name("description").value(it.description)
                    }
                }
            }

            endObject()
        }
    }
}

class App {
    companion object {
        @JvmStatic fun main(args: Array<String>) {
            val tm = TestModel(12, description = "Hello desc")
            val tm2 = TestModel(23, picture = "https://www.pexels.com/photo/daylight-forest-glossy-lake-443446/")
            val tm3 = TestModel(12, "Hello desc", "https://www.pexels.com/photo/daylight-forest-glossy-lake-443446/")

            val gson = GsonBuilder().registerTypeAdapter(TestModel::class.java, TesModelTypeAdapter()).create()

            System.out.println(gson.toJson(tm))
            System.out.println(gson.toJson(tm2))
            System.out.println(gson.toJson(tm3))
        }
    }
}

enter image description here

答案 1 :(得分:1)

这实际上是一种忽略未通过@Exposed批注标记的字段的方法。为了使它起作用,在实例化Gson时应使用特殊的配置。 Here是实现此目的的方法。

简便的方法是将字段标记为@Transient。这样就不会被序列化和反序列化。

答案 2 :(得分:0)

我想为您提供其他方法,而无需手动进行序列化/反序列化。

data class TestModel(
    val id: Int,
    val description: String? = null,
    val picture: String? = null)

当您从数据类创建json

val params = TestModel(id = 1, description = "custom text")

val params = TestModel(id = 1, picture = "picture path")
  

如果其中一个字段为数据类的null,则GSON跳过该字段   自动。