Hello, i'm trying to write a custom serializer and...
# serialization
p
Hello, i'm trying to write a custom serializer and i'm getting an exception:
Can't locate argument-less serializer for class kotlinx.serialization.json.JsonObject. For generic classes, such as lists, please provide serializer explicitly.
Copy code
@Serializable
    class Foo {
        @Serializer(forClass = Foo::class)
        companion object : KSerializer<Foo> {

            override fun serialize(encoder: Encoder, obj: Foo) {
                encoder.encode(JsonObject::class.serializer(), JsonObject(mapOf("foo" to JsonLiteral("bar"))))
            }

            override fun deserialize(decoder: Decoder): Foo {
                TODO()
            }
        }
    }

    fun main() {
        Json.stringify(Foo.serializer(), Foo())
    }
n
looks like it might have a problem with the lack of any property
and you can also do:
@Serializable(with=Foo.Companion::class)
p
Copy code
@Serializable(with = FooSerializer::class)
    class Foo(val bar: String)

    @Serializer(forClass = Foo::class)
    object FooSerializer : KSerializer<Foo> {

        override fun serialize(encoder: Encoder, obj: Foo) {
            encoder.encode(JsonObject::class.serializer(), JsonObject(mapOf("bar" to JsonLiteral("value"))))
        }

        override fun deserialize(decoder: Decoder): Foo {
            TODO()
        }
    }
    
    fun main() {
        Json.stringify(FooSerializer, Foo("value"))
    }
I'm still getting the same error
n
i assume your goual is to serialize it to
{ "bar", "value" }
? then i think you should use
encoder.startStructure
and
.encodeString
and finish it with
.endStructure
s
Use
JsonObjectSerializer
instead of
JsonObject::class.serializer()
p
JsonObjectSerializer
is internal i can not use it
The use case is that i want to wrap the actual object and add additional metadata fields e.g. `data class Foo(val bar: String)`should serialize to
{"type": "X", "object": {"bar":"value"}}
. I do not want to add any extra classes to achieve this serialization.
n
try this
Copy code
val jsonOutput = encoder as JsonOutput
jsonOutput.encodeJson(JsonObject(mapOf("bar" to JsonLiteral("value"))))
👍 1
the output this produces is:
Copy code
{"bar":"value"}
{
    bar: value
}
{bar:value}
i would kinda like to have only keys unquoted..
also no clue how you want to parse this.. but i bet the same can be done with the decoder
obviously you will need to use
as?
and add some errorhandling in case it get called from something other than
Json()
and.. @sandwwraith is
JsonOutput
the correct type here ? or would there be something more appropritate ?
the code for deserialization seems to be:
Copy code
val jsonInput: JsonInput = decoder as JsonInput
val element: JsonElement = jsonInput.decodeJson()
btw if you figure out a low boilerplate pattern for switching between serializers based on a type property poke me
p
I will only use json format. I think encoder should have been a generic type which extends Encoder because most of the systems have one format for serialization, unless you're writing a library.
thank you for your help @Nikky