Serving JSON content in Ktor as described in HTTP API - Quick Start - Ktor, as shown in the examples, works for common collections (lists, maps, etc.) and data classes. However, if I want to serialize a class that is not a data class and has fields that I want to exclude, how do I specify the fields to be serialized and their serialized names? Assume that I am using Gson, can I do it in the same way as serializing a class object using Gson directly?
Using Gson, you have a couple of options to the best of my knowledge.
1. Using Transient
If you mark a field with @Transient
(transient
in Java) this will be excluded from serialization:
data class Foo(
@Transient val a: Int,
val b: Int)
Here, b
will be serialized and a
will not.
This comes with a huge downside - almost every framework in java takes @Transient
into account and sometimes you don't want it to be serialized by Gson, but you might want to persist it to the database for example (if you'd be using the same class for both). To account for this, there's another option, using @Expose
.
2. Using Expose
You need to create the gson
instance using the builder:
val gson = GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();
Now, fields without @Expose
won't be serialized:
data class Foo(
val a: Int,
@Expose val b: Int)
Again, a
will not be serialized, but b
will.
3. Using exclusion strategies
A more advanced method is the usage of exclusion strategies. This allows for loads of introspections on the fields. From custom annotations to the field name or type.
Again, you need to create a gson
with a builder:
val gson = GsonBuilder()
.addSerializationExclusionStrategy(strategyInstance)
.create();
And you define a strategy like:
object : ExclusionStrategy() {
override fun shouldSkipField(field: FieldAttributes): Boolean {
}
override fun shouldSkipClass(clazz: Class<*>): Boolean {
}
}
inside shouldSkipField
you return true
when you don't want to serialize the field and false
when you do. Because it receives a FieldAttributes
you can get a lot of properties from the field such as name and annotations. This allows for very fine-grained control.
Lastly, you can set this strategy for deserialization as well and for both - addDeserializationExclusionStrategy
and setExclusionStrategies
.