Home > Back-end >  How to serialize an inner class as a single value with GSON
How to serialize an inner class as a single value with GSON

Time:05-17

Assume the following two clases

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

The JSON serialization of this is {"name":"Bob","address":{"city":"London","postcode":"LO12 345"}}

On the API output, I want to serialise the address as a single string, and not an object. e.g. {"name":"Bob","address":"London, LO12 345"}

I can achieve this if I write a custom serializer for Person, and even managed to work around the issue of only changing this single attribute instead of everything. However, I still have the issue that I now need to change how every single class that uses Address.

I am wondering if instead, there is a way to writte a serializer for Address that would only return a value instead of an object, much like a primive does. Then I am hoping that every single class that uses Address, would behave as if Address was a String straight away and serialize it as such.

Is such a thing possible?

CodePudding user response:

You can write a serialiser for Address like this:

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

}

This serialiser outputs a JsonPrimitive, which is a string containing the city and postcode.

You can then register this when creating a Gson:

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

Output:

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

CodePudding user response:

Not exactly sure if this is what you're looking for but what if you simply make it a data class? Like

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

Then the toString() of it is a very descriptive string, and similar objects also count as equal, like

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
  • Related