Я пишу собственный сериализатор для kotlin .serialization, который интерпретирует переменную JSON как строку независимо от ее типа. Десериализация работает нормально. Но у меня возникли проблемы с сериализацией String снова в исходную структуру.
На данный момент я просто десериализую значение как String. Но это добавляет дополнительные кавычки вокруг значения и приводит к проблемам.
Вот быстрый пример:
//
//Custom serializer:
//
object JsonToStringSerializer : KSerializer<String> {
override val descriptor: SerialDescriptor = PrimitiveDescriptor("JsonToStringSerializer", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: String) {
if(value.startsWith("[") || value.startsWith("{")) {
encoder.encodeString(value) //<-- bad solution
println("Oh no! Object has been turned into a String!")
}
else //will also encode Int, Float, Boolean, ... into String - but that is ok
encoder.encodeString(value)
}
override fun deserialize(decoder: Decoder): String {
val output = (decoder as JsonInput).decodeJson().toString()
return if(output.startsWith("\""))
output.substring(1, output.length-1)
else output
}
}
//
//Data structure for test:
//
@Serializable
class Test (
@Serializable(with = JsonToStringSerializer::class) val objValue: String,
val stringValue: String
)
//
//test logic:
//
fun test() {
val jsonString = "{\"objValue\": [1,2], \"stringValue\": \"test\"}"
val obj = Json(JsonConfiguration.Stable).parse(Test.serializer(), json)
val newJsonString = Json(JsonConfiguration.Stable).stringify(Test.serializer(), obj)
println(newJsonString)
//expected result: {"objValue": [1,2], "stringValue": "test"}
//actual result: {"objValue": "[1,2]", "stringValue": "test"}
}
После некоторого рытья я обнаружил, что encoder
в serialize()
принадлежит класс StreamingJsonOutput
. Я могу придумать три возможных решения. Но я столкнулся с стеной с каждым из них:
- Если бы у меня был способ напрямую
print()
на composer
из StreamingJsonOutput
, я мог бы добавить String вручную к выходным данным. Но, к сожалению, composer
является частным (и StreamingJsonOutput
также внутренним). - Другой способ - использовать конфигурацию
unquotedPrint
, которая будет создавать строки без кавычек. Но тогда и в stringValue
не было бы кавычек. Так что мне нужен способ просто изменить конфигурацию только временно. - Я мог бы просто десериализовать
value
String из serialize()
в реальный объект, а затем просто позволить кодировщику правильно сериализовать его. Проблема, помимо накладных расходов на производительность, заключается в том, что я не знаю, какую структуру данных ожидать в value
. Поэтому я не могу десериализовать его.
Надеюсь, у кого-то есть идея, как с этим бороться. Большое спасибо! :)