Как правильно сериализовать / десериализовать с Gson сложный объект в kotlin? - PullRequest
0 голосов
/ 16 мая 2018

У меня есть следующие поля для строки JSON:

action=surveyEventName
EventObject= serialized Event object (So in this field I want to serialize an object with Gson.

Проблема, с которой я столкнулся, заключается в том, что при попытке сериализации объекта Event я получаю ANR.Итак, я думаю, что могу сделать что-то не так с точки зрения настройки сериализации Gson.

класс событий определяется следующим образом:

class Event {

private var mActionName = ""
private var mId = ""
private lateinit var mConditions: MutableList<(Unit) -> Boolean>
private lateinit var mActions: MutableList<(Unit) -> Boolean>

fun getActionName(): String {
    return this.mActionName
}

fun setActionName(actionName: String) {
    this.mActionName = actionName
}

fun getId(): String {
    return this.mId
}

fun setId(id: String) {
    this.mId = id
}

fun addSingleCondition(condition: (Unit) -> Boolean) {
    if(::mConditions.isInitialized) {
        mConditions.add(condition)
    } else {
        mConditions = mutableListOf(condition)
    }
}

fun addSingleAction(action: (Unit) -> Boolean) {
    if(::mActions.isInitialized) {
        mActions.add(action)
    } else {
        mActions = mutableListOf(action)
    }
}

companion object {
    fun serializeEventList(event: List<Event>): String {
        return Gson().toJson(event) // ANR HERE!
    }

    fun deserializeEventList(jsonString: String): MutableList<Event> {
        return Gson().fromJson(jsonString,
                object : TypeToken<List<Event>>() {}.type)
    }
}
}

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

Вот мой тестовый блок:

//TESTBLOCK
fun testEvent() {
    //create test event
    val event = Event()
    event.setId("1")
    event.setActionName("testtag")
    event.addSingleCondition { testCondition1() }
    event.addSingleCondition { testCondition2() }
    event.addSingleAction { testAction1() }
    event.addSingleAction { testAction2() }
    val events = listOf(event)
    //create test JSON
    val jsonObject = JSONObject()
    jsonObject.put("tagfield", "testtag")
    val serializedObjectString = event.serializeEventList(events) 
    jsonObject.put("eventobjectfield", serializedObjectString)

}

, после чего я десериализирую поле Eventobject JSON, чтобы использоватьСнова объект события, но когда я пытаюсь сериализовать, я получаю ANR.

Я не уверен, что Gson не работает из-за лямбд, которые я добавил к объекту Event.Что я могу делать не так?

1 Ответ

0 голосов
/ 28 марта 2019

У меня была эта проблема с несколькими реализациями, пока я не понял, что Gson работает лучше, если вы осторожны в момент его использования.Я обнаружил две вещи, которые не сработали в моем коде:

1) lateinit var: по какой-то причине Gson зависает при разборе класса с этими переменными.2) Наследование переменных-членов или свойств с переопределенными значениями: в основном,

, если я переопределяю унаследованное значение, Gson жалуется, что у меня есть две переменные, определенные с таким же именем, как показано ниже:

open class Person() {
    var id = 0
    var name = ""
    var age = 0
}

class AdultPerson() : Person() {
    override var age = 18
}

Там Гсон будет жаловаться, что у объекта есть 2 переменные с одинаковым именем age.Таким образом, чтобы решить эту проблему, мне нужно изменить значение по умолчанию age в блоке конструктора или блоке init, чтобы не перекрывать переменную.

Итак, позаботившись об этих двух вещах, мне удалось заставить Gson конвертировать мои объектыв строки, даже если они имеют сложное наследование, коллекции или классы с переменными, которые являются коллекциями.

Я оптимизировал свой предыдущий синтаксический анализатор Gson, чтобы он работал с другими классами, пока он работает нормально:

GsonParser.kt

object GsonParser {
    inline fun <reified T> toJson(src: T): String {
        return Gson().toJson(src)
    }

    inline fun <reified T> fromJson(src: String): T {
        val type = object : TypeToken<T>() {}.type
        return Gson().fromJson(src, type)
    }
}

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...