如何使用 GSON 将内部 class 序列化为单个值

How to serialize an inner class as a single value with GSON

假设有以下两个类

class Person internal constructor(var name: String, var address: Address)
class Address internal constructor(var city: String, var postcode: String)

这个的JSON连载是 {"name":"Bob","address":{"city":"London","postcode":"LO12 345"}}

在 API 输出中,我想将地址序列化为单个字符串,而不是对象。例如{"name":"Bob","address":"London, LO12 345"}

如果我为 Person 编写一个自定义序列化程序,我就可以实现这一点,甚至设法解决只更改这个单一属性而不是所有内容的问题。但是,我仍然有一个问题,我现在需要更改使用 Address.

的每个 class 的方式

我想知道是否有一种方法可以为 Address 编写一个序列化程序,它只会 return 一个值而不是一个对象,就像原始数据一样。然后我希望每个使用 Address 的 class 都会表现得好像 Address 是一个 String 一样,并像这样序列化它。

这样的事情可能吗?

不确定这是否是您要查找的内容,但如果您只是将其作为数据 class 会怎样?喜欢

data class Address internal constructor(var city: String, var postcode: String)

那么它的toString()就是一个很有描述性的字符串,相似的对象也算相等,比如

val a = Address("London", "LO12 345")
val b = Address("London", "LO12 345")

println(a) //prints: Address(city=London, postcode=LO12 345)
println(a == b) //prints: true

您可以像这样为 Address 编写序列化程序:

class AddressSerialiser: JsonSerializer<Address> {
    override fun serialize(p0: Address, p1: Type?, p2: JsonSerializationContext?) =
        JsonPrimitive("${p0.city}, ${p0.postcode}")

}

这个序列化器输出一个 JsonPrimitive,这是一个包含城市和邮政编码的字符串。

然后您可以在创建 Gson 时注册它:

val gson = GsonBuilder()
    .registerTypeAdapter(Address::class.java, AddressSerialiser())
    .create()
println(gson.toJson(Person("John", Address("Cambridge", "CB5 8HX"))))

输出:

{"name":"John","address":"Cambridge, CB5 8HX"}