Search code examples
kotlinserializationgson

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


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?


Solution

  • 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"}