Is there a way to completely prevent the serialize...
# serialization
r
Is there a way to completely prevent the serializer from ever serializing a
null
value anywhere?
s
What's your use-case?
r
The Algolia API which does not accept
null
as a value.
null
is different than not present for this API (and a lot of others)
s
If you have
null
as default value for some variable, you can use
Json(encodeDefaults = false)
to drop them during serialization process
r
That’s really not a good solution as I could have other default values than
null
that I would like to encode anyway
It also doesn’t seem to work right now, I’ll have to investigate tomorrow...
d
Is it possible to just avoid the use of
null
at all?
r
How? The Algolia API is like it is and I have to use it
And as I said it’s not the only API doing this. All Json serializers implement a way to ignore nulls for a reason... It’s the same thing for top-level Json array, it’s a bad practice but it’s there and serializers have to implement it
For this use case I think I have no other choice than implementing a whole custom serializer for a dead simple model.
Note that I agree with the philosophy of not having implicit optionals, I would like to serialize those null values, but philosophies often forget that there is a real world. And when a whole API does not support null values, I don’t want to use workarounds like putting default values everywhere in my code. An optional key is not a mandatory key with a default value, these are different things.
e
same goes for Protobuf, null just means don’t serialize the field. so far I’ve been unsuccessful in making this work
d
Can you install an anti-corruption layer?
Personally I prefer default values.
I get rid of
null
at every opportunity.
r
@dewildte that’s unrelated. You’re talking in a context where you have all the power. That does not happen in the real world
Most of the time you implement an API you don’t have any control on
@sandwwraith
encodeDefaults
absolutely does not work.
s
Well, you can try simpler approach first: serialize things to
JsonElement
, then just edit it to filter out nulls
r
Yes, that’s what I used, it works:
Copy code
@Serializable
internal data class SearchQuery(
    val query: String,
    val aroundLatLng: String?,
    val facetFilters: List<FacetFilter>?
) {

    @Serializer(SearchQuery::class)
    companion object : KSerializer<SearchQuery> {

        override val descriptor = object : SerialClassDescImpl(SearchQuery::class.simpleName!!) {
            init {
                addElement("query")
                addElement("aroundLatLnt", true)
                addElement("facetFilters", true)
            }
        }

        override fun serialize(encoder: Encoder, obj: SearchQuery) {
            encoder
                .beginStructure(descriptor)
                .apply {
                    encodeStringElement(descriptor, 0, obj.query)
                    obj.aroundLatLng?.let {
                        encodeStringElement(descriptor, 1, it)
                    }
                    obj.facetFilters?.let {
                        encodeSerializableElement(descriptor, 2, FacetFilter.serializer().list, it)
                    }
                }
                .endStructure(descriptor)
        }

        override fun deserialize(decoder: Decoder): SearchQuery {
            throw NotImplementedError()
        }

    }

}
Of course I would prefer to only need the first 4 lines...
@sandwwraith what do you think of a way to add some kind of interceptor that could act between the JsonElement phase and the String phase, for this case but also potentially many more?
Because I’m using Ktor and serializing to JsonElement myself then removing nulls every time one or more value is optional doesn’t sound like a more practical solution than the custom serializer to me, unless I missed some kind of interceptor like that that I could setup only once
s
Hm, I think it is possible to write such interceptor using ktor pipelines
d
You said my statements are unrelated but an anti corruption layer is directly related.
r
Right, but it’s an overengineered solution to a very simple problem in this case
d
You have system A that takes some data in a manner that makes you unhappy. And you have system B that is nice and pretty. System A and B do not work together correctly so you need an adapter or translater, AKA an anti corruption layer. How is that not going to solve your issue?
It's like American wall sockets vs UK wall sockets.
Is it really? A simple mapper is not as complicated as a custom serializer.
r
Note that I didn’t say it was not a solution. It’s even the solution I have to implement anyway, either with a custom serializer or by serializing the model myself into a
JsonObject
instance, removing
null
values by hand and converting that to
String
before I pass it to Ktor as a body.
It’s just something that the library should do. Because that’s what all Json serializers (but this one) allow, ignoring
null
values entirely.
d
Make the change easy and then make the easy change. - Kent Beck It sounds like you could take that approach here.
Like I said, if null is the problem then remove the null and you have no problem.
r
Good theory but I live in the real world
d
Anyway I tried to be helpful now you are just being snide. Good day to you sir.