JSON Enum десериализации ломает котлин нуль-безопасности - PullRequest
0 голосов
/ 17 февраля 2019

Я использую Kotlin data classes и GSON для десериализации схем JSON и реализации значений по умолчанию для защиты от нулевых объектов в JSON.Кроме того, перечисления JSON int соответствуют значениям перечисления Kotlin с использованием аннотации @SerializedName:

data class Person(@SerializedName("name")
           val name: String = ",
           @SerializedName("age")
           val age: Int = 0,
           @SerializedName("hairColor")
           val hairColor: Color = Color.NONE)

enum class Color{
    @SerializedName("1")
    BROWN,
    @SerializedName("2")
    BLONDE,
    NONE
}

Сосредоточение внимания на десериализации перечисления - это хорошо работает в ситуациях, когда поле соответствует известному перечислению или если поле полностью отсутствуетиз JSON, в этом случае будет реализовано перечисление по умолчанию.

НО - если полученное перечисление в JSON не сопоставляется с известным значением перечисления в моем перечислении kotlin - результирующийдесериализованный enum будет нулевым !!

{"name":"Joe","age":10,"hairColor":1} ->
Person(name=Joe, age=10, hairColor=BROWN)

{"name":"Jim"} ->
Person(name=Jim, age=0, hairColor=NONE)

{"name":"Jeff", "age":8,"hairColor":3) ->
Person(name=Jane, age=8, hairColor=null)

Gson обманывает нулевой механизм безопасности Kotlin, присваивая null ненулевому типу.Вопрос - как сопоставить неизвестные JSON-перечисления с глухими Kotlin-перечислениями?Моя цель - поддерживать нулевую безопасность с помощью простой реализации.

PS - я знаю, что могу просто проанализировать перечисления JSON как Ints и десериализовать их позже, или использовать вспомогательные поля и пользовательские геттеры, но мне нравится элегантность исинтаксический анализ типа безопасности непосредственно к перечислениям Kotlin.

1 Ответ

0 голосов
/ 14 августа 2019

Я написал оболочку Kotlin (называемую Arson) для Gson, которая добавляет недостающие значения по умолчанию к десериализованным объектам.Кроме того, он также проверяет наличие нулевых значений, которые нарушают ненулевую безопасность Kotlin.

Проверьте это: https://github.com/taskbase/arson

Используйте его в своем проекте:

<dependency>
    <groupId>com.taskbase.arson</groupId>
    <artifactId>arson</artifactId>
    <version>1.0</version>
</dependency>

class ArsonTest {

    @Test
    fun testEnumDeserialization() {
        val json = "{'name':'Jim', 'hairColor':'3'}"

        // Gson deserializes the value to null
        val p1 = Gson().fromJson(json, Person::class.java)
        assertNull(p1.hairColor)

        // The wrapper replaces null with the default value
        val p2 = Arson(gson = Gson()).fromJson(json, Person::class.java)
        assertEquals(Color.NONE, p2.hairColor)
    }
}

data class Person(
    val name: String = "",
    val age: Int = 0,
    val hairColor: Color = Color.NONE
)

enum class Color {
    @SerializedName("1")
    BROWN,
    @SerializedName("2")
    BLONDE,
    NONE
}

Я также боролся с отсутствием поддержки у Котона у Гсона.Gson - это библиотека Java, которая не понимает систему типов Kotlin.Я протестировал несколько других библиотек JSON, но ни одна из них не работала достаточно хорошо.Поэтому я написал функцию, которая использует библиотеку отражений Kotlin для создания глубокой копии объекта, которая добавляет недостающие значения по умолчанию.

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