【问题标题】:Gson Serialize & Deserialize Enums to ints with Generalized codeGson 使用通用代码将枚举序列化和反序列化为整数
【发布时间】:2018-06-20 14:35:24
【问题描述】:

我正在开发自定义 JsonSerializer 和 JsonDeserializer 我想将json(ints)序列化为枚举并将枚举反序列化为int

我为此创建了一个接口,其中枚举有一个名为 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 吗?

【问题讨论】:

    标签: java json enums kotlin


    【解决方案1】:

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

    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)
    

    【讨论】:

      猜你喜欢
      • 2013-05-20
      • 2021-11-28
      • 2016-10-16
      • 2018-07-31
      • 1970-01-01
      • 1970-01-01
      • 2017-04-07
      • 2015-11-15
      • 1970-01-01
      相关资源
      最近更新 更多