I'm trying to build a custom serializer that would...
# serialization
j
I'm trying to build a custom serializer that would encode
Copy code
Filter.NOT(
    Filter.Field(
        name = "foo", value = "bar"
    )
)
to exactly this (without type field or name and value fields, just this):
Copy code
{
  "not": {
    "foo": "bar"
  }
}
this is what I'm playing with currently, but I'm stuck:
Copy code
@Serializable
sealed interface Filter {

    ... 
    
    @Serializable
    @SerialName("not")
    class NOT(val not: Filter): Filter

    @Serializable(with = Field.Companion::class)
    data class Field(
        val name: String,
        val value: String
    ) : Filter {

        companion object : KSerializer<Field> {

            override val descriptor: SerialDescriptor
                get() = mapSerialDescriptor<String, String>()

            override fun serialize(encoder: Encoder, value: Field) {
                encoder.encodeStructure(mapSerialDescriptor<String, String>()) {
                    mapOf("a" to "b", value.name to value.value) // this does nothing due to block: (...) -> Unit
                }
            }
            override fun deserialize(decoder: Decoder): Field = TODO()
        }
    }
}
currently outputs:
Copy code
{
  "not": {
    "type": "kotlin.collections.HashMap"
  }
}
I'm probably not using mapSerialDescriptor correctly, but not sure how to use it correctly. any suggestions?
Trying with
Copy code
@Serializable(with = Field.Companion::class)
    data class Field(
        val name: String,
        val value: String
    ) : Filter {
        companion object : JsonTransformingSerializer<Field>(Field.serializer()) {
            override fun transformSerialize(element: JsonElement): JsonElement {
                return JsonObject(mutableMapOf<String, JsonElement>().apply {
                    put("foo", JsonPrimitive("bar"))
                })
            }
        }
    }
is throwing:
Copy code
Caused by: java.lang.NullPointerException: Cannot invoke "com.jvaas.testing.model.filter.Filter$Field$Companion.serializer()" because "com.jvaas.testing.model.filter.Filter$Field.Companion" is null
a
using a companion object for the KSerializer might be interfering with the KxS compiler plugin. Try making it a regular object instead of a companion object.
j
Copy code
@Serializable(with = FieldSerializer::class)
    data class Field(
        val name: String,
        val value: String
    ) : Filter


    object FieldSerializer : JsonTransformingSerializer<Field>(Field.serializer()) {
        override fun transformSerialize(element: JsonElement): JsonElement {
            return JsonObject(mutableMapOf<String, JsonElement>().apply {
                put("foo", JsonPrimitive("bar"))
            })
        }
    }
getting a similar error
Copy code
Exception in thread "main" java.lang.ExceptionInInitializerError
	at com.jvaas.testing.model.filter.Filter$NOT.<clinit>(Filter.kt:62)
	at Test.main(Test.kt:17)
Caused by: java.lang.NullPointerException: Parameter specified as non-null is null: method kotlinx.serialization.json.JsonTransformingSerializer.<init>, parameter tSerializer
	at kotlinx.serialization.json.JsonTransformingSerializer.<init>(JsonTransformingSerializer.kt)
	at com.jvaas.testing.model.filter.Filter$FieldSerializer.<init>(Filter.kt:73)
	at com.jvaas.testing.model.filter.Filter$FieldSerializer.<clinit>(Filter.kt)
i tried making the FieldSerializer object a class instead of an object, but then I get a StackOverflow error as the class is instantiated over and over due to Field.serializer() Working around the Stackoverflow error
Copy code
@Serializable(with = FieldSerializer::class)
    data class Field(
        val name: String,
        val value: String
    ) : Filter {
        companion object {
            val serializer = Field.serializer()
        }
    }

    object FieldSerializer : JsonTransformingSerializer<Field>(Field.serializer) {
        override fun transformSerialize(element: JsonElement): JsonElement {
            return JsonObject(mutableMapOf<String, JsonElement>().apply {
                put("foo", JsonPrimitive("bar"))
            })
        }
    }
I'm once again getting the same error
Copy code
Exception in thread "main" java.lang.ExceptionInInitializerError
	at com.jvaas.testing.model.filter.Filter$NOT.<clinit>(Filter.kt:62)
	at Test.main(Test.kt:17)
Caused by: java.lang.NullPointerException: Parameter specified as non-null is null: method kotlinx.serialization.json.JsonTransformingSerializer.<init>, parameter tSerializer
	at kotlinx.serialization.json.JsonTransformingSerializer.<init>(JsonTransformingSerializer.kt)
	at com.jvaas.testing.model.filter.Filter$FieldSerializer.<init>(Filter.kt:76)
	at com.jvaas.testing.model.filter.Filter$FieldSerializer.<clinit>(Filter.kt)
	... 2 more