Сериализация Kotlin в JSON: как игнорировать фактический тип поля - PullRequest
0 голосов
/ 13 сентября 2018

Я новичок в Kotlin и еще новее в Сериализация Kotlin , и я пытаюсь преобразовать класс данных Kotlin в JSON.Посмотрите на следующий пример кода:

import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JSON

fun main(args: Array<String>) {
    println(JSON.stringify(BaseClass1("abc")))
    println(JSON.stringify(BaseClass2("abc")))
}

@Serializable
data class BaseClass1(
        val a: String
)

@Serializable
data class BaseClass2(
        val a: Any
)

Вывод:

{"a":"abc"}
{"a":["kotlin.String","abc"]}

Поэтому я сохраняю String в переменной типа Any (которая должна быть совершенно корректной),Однако это приводит к тому, что сериализованное значение является массивом типа и значения.Это также происходит с другими классами и подклассами (например, когда я расширяю тип поля).

Как я могу получить stringify, чтобы всегда использовать значение, независимо от фактического типа поля?Я хочу, чтобы второй stringify результат указанной выше программы совпадал с первым.

Ответы [ 2 ]

0 голосов
/ 16 сентября 2018

вы можете упростить ваше решение, пометив сериализатор с помощью @Serializer(forClass=BaseClass1:class), затем вы можете пропустить переопределения load и serialClassDesc .. плагин сгенерирует для вас значения по умолчанию

0 голосов
/ 14 сентября 2018

Мне удалось сделать это с помощью специального сериализатора.

Единственным недостатком является то, что, поскольку я не сохраняю тип, я не могу снова десериализовать объект, но мне нужно только сериализоваться в моей программе.

@Serializable
data class BaseClass2(
        @Serializable(with = PlainObjectSerializer::class) val a: Any
)


object PlainObjectSerializer : KSerializer<Any> {
    override val serialClassDesc: KSerialClassDesc
        get() = SerialClassDescImpl("") //PlainObjectDesc

    override fun save(output: KOutput, obj: Any) {
        val saver = serializerByValue(obj, output.context)
        output.writeSerializableValue(saver, obj)
    }

    override fun load(input: KInput): Any {
        throw Exception("This serializer can only be used for serialization!")
    }
}

РЕДАКТИРОВАТЬ: Как @ Nikky предложил , этот код может быть еще более упрощен с помощью плагина сериализации:

@Serializer(forClass = BaseClass2::class)
object PlainObjectSerializer : KSerializer<Any> {
    override fun save(output: KOutput, obj: Any) {
        val saver = serializerByValue(obj, output.context)
        output.writeSerializableValue(saver, obj)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...