1

我正在研究自定义 JsonSerializer 和 JsonDeserializer 我想将 json(整数)序列化为枚举并将枚举反序列化为整数

为此,我创建了一个接口,其中枚举有一个名为 fromValue 的函数,它应该采用反序列化的值并返回枚举:

interface EnumSerializationInterface {
    val value: Int
    fun fromValue(value: Int): EnumSerializationInterface?
}

示例枚举:

enum class TestDummyEnumTestEnum(override val value: Int): 
EnumSerializationInterface {
    ENUM1(1),
    ENUM2(2);

    override fun fromValue(value: Int): EnumSerializationInterface? {
        for (enum in TestDummyEnumTestEnum.values()) {
            if (enum.value == value) {
                return enum
            }
        }
        return null
    }
}

我的序列化器工作但我在反序列化时遇到问题,我的序列化器和反序列化器:

class EnumDeserializer: JsonDeserializer<EnumSerializationInterface> {
    override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): EnumSerializationInterface {
        val value = json.asInt()
        return typeOfT.fromValue(value)   
        /*THIS DOES NOT WORK*/
    }
}

class EnumSerializer: JsonSerializer<EnumSerializationInterface> {
    override fun serialize(src: EnumSerializationInterface?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
        return context!!.serialize(src!!.value)
    }
}

我的问题是我无法从 typeOfT 获取“fromValue”函数。

有人知道如何获得实际的 typeOfT 吗?

4

1 回答 1

0

这是我的解决方案。我使用伴随对象来构建枚举查找。这使我的编码枚举更易于理解,但在声明枚举时样板文件更少:

interface CodedEnum {
    val code: Int
}

// It has to take class as parameter, since it is not possible to access T.values()
// This is Java generics limitation: https://stackoverflow.com/questions/2205891/iterate-enum-values-using-java-generics
open class CodedEnumLookup<E>(klass: Class<E>) where E: Enum<E>, E: CodedEnum {
    val lookup = klass.enumConstants.associate { it.code to it }

    init {
        // Make sure no duplicate codes
        check(lookup.size == klass.enumConstants.size)
    }

    fun get(code: Int): E {
        return lookup[code]!!
    }
}

示例用法:

enum class Color(override val code: Int): CodedEnum {

    RED(0),
    GREEN(1),
    BLUE(2);

    companion object: CodedEnumLookup<Color>(Color::class.java)
}

在 Gson 中,稍微使用了 Kotlin 的反射:

object CodedEnumSerializer : JsonSerializer<CodedEnum>, JsonDeserializer<CodedEnum> {
    override fun serialize(src: CodedEnum, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
        return JsonPrimitive(src.code)
    }

    // Not sure about how performant this solution is
    override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): CodedEnum {
        return ((typeOfT as Class<*>).kotlin.companionObjectInstance as CodedEnumLookup<*>).get(json.asInt) as CodedEnum
    }
}

GsonBuilder().registerTypeHierarchyAdapter(CodedEnum::class.java, CodedEnumSerializer)
于 2018-11-26T22:30:02.927 回答