Reputation: 8968
Is it possible to encode / decode any valid json objects in string format in a custom serializer. For example the code below but not let it serialize as json string but as any valid JSON with unknown structure?
object JsonObjectSerializer : KSerializer<JsonObject> {
override val descriptor = PrimitiveSerialDescriptor("JsonObject", PrimitiveKind.STRING)
override fun deserialize(decoder: Decoder): JsonObject =
JsonObject(decoder.decodeString())
override fun serialize(encoder: Encoder, value: JsonObject): Unit =
encoder.encodeString(value.encode())
}
Out would be something like..
{
"some": "data",
"jsonObject": "{\"this\": \"should not be a string\"}"
}
But wanted output would be..
{
"some": "data",
"jsonObject": {"this": "should not be a string"}
}
Upvotes: 4
Views: 4822
Reputation: 19100
encoder.encodeJsonElement
might do what you want.
I use encodeJsonElement
myself in the implementation of UnknownPolymorphicSerializer<P, W>
A serializer for polymorph objects of type [P] which wraps extending types unknown at runtime as instances of type [W].
I extract the known structure and wrap the the unknown structure. Maybe a similar use case than you are after? The specifics, and use case, are fairly complicated, but documented in "UnknownPolymorphicSerializer: (De)serializing unknown types".
@InternalSerializationApi
override fun serialize( encoder: Encoder, value: P )
{
// This serializer assumes JSON serialization with class discriminator configured for polymorphism.
// TODO: It should also be possible to support array polymorphism, but that is not a priority now.
if ( encoder !is JsonEncoder )
{
throw unsupportedException
}
getClassDiscriminator( encoder.json ) // Throws error in case array polymorphism is used.
// Get the unknown JSON object.
check( value is UnknownPolymorphicWrapper )
val unknown = Json.parseToJsonElement( value.jsonSource ) as JsonObject
// HACK: Modify kotlinx.serialization internals to ensure the encoder is not in polymorphic mode.
// Otherwise, `encoder.encodeJsonElement` encodes type information, but this is already represented in the wrapped unknown object.
AccessInternals.setField( encoder, "writePolymorphic", false )
// Output the originally wrapped JSON.
encoder.encodeJsonElement( unknown )
}
P.s. AccessInternals
is an expected implementation of mine to be able to use kotlin reflect, not supported on JS, since this is a multiplatform library.
Upvotes: 1