自定义布尔反序列化程序在Gson中不工作

evrscar2  于 2022-11-06  发布在  其他
关注(0)|答案(2)|浏览(251)

我必须将0反序列化为false,将1反序列化为true
我创建了这个类:

class IntBooleanDeserializer : JsonDeserializer<Boolean?> {
    override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): Boolean? {
        json?.let {
            return json.asInt == 1
        }

        return null
    }
}

并注册了它:

private val gson = GsonBuilder()
            .registerTypeAdapter(Boolean::class.java, IntBooleanDeserializer())
            .create()

并为此创建了测试类:

data class BooleanClass(val value: Boolean?)

然后道:

gson.fromJson("{\"value\": 0}", BooleanClass::class.java)

此代码抛出异常:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a boolean but was NUMBER at line 1 column 12 path $.value

看起来Gson并没有将我的反序列化器用于Boolean?,而是成功地将其他自定义反序列化器用于其他类型(例如,用于枚举)。
为什么?

cvxl0en2

cvxl0en21#

您正在为Boolean::class.java注册反序列化器,它是boolean,而实际上您需要的类型是Boolean?,它将转换为java.lang.Boolean
要获得java.lang.Boolean,您必须使用Boolean::class.javaObjectType进行注册。
您还会发现所有原始 Java 类型都有相同的行为。

x4shl7ld

x4shl7ld2#

受@tynn的答案和这个post的启发,我设计了两个TypeAdater来覆盖Kotlin中的BooleanBoolean?类型。

private val TRUE_STRINGS: Array<String> = arrayOf("true", "1")

class BooleanObjectTypeAdapter : JsonDeserializer<Boolean?>, JsonSerializer<Boolean?> {

    override fun serialize(src: Boolean?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
        return if (src == null) {
            JsonNull.INSTANCE
       } else {
           JsonPrimitive(src)
       }
    }

    override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): Boolean? {
        if (json == null || json.isJsonNull) {
            return null
        }

        return when {
            json !is JsonPrimitive -> false
            json.isBoolean -> json.asBoolean
            json.isNumber -> json.asNumber.toInt() == 1
            json.isString -> TRUE_STRINGS.contains(json.asString.lowercase())
            else -> false
        }
    }
}

class BooleanPrimitiveTypeAdapter : JsonDeserializer<Boolean>, JsonSerializer<Boolean> {

    override fun serialize(src: Boolean?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
        return if (src == null) {
            JsonPrimitive(false)
        } else {
            JsonPrimitive(src)
        }
    }

    override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): Boolean {
        if (json == null || json.isJsonNull) {
            return false
        }

        return when {
            json !is JsonPrimitive -> false
            json.isBoolean -> json.asBoolean
            json.isNumber -> json.asNumber.toInt() == 1
            json.isString -> TRUE_STRINGS.contains(json.asString.lowercase())
            else -> false
        }
    }
}

您可以通过以下方式注册这些适配器

GsonBuilder()
    .registerTypeAdapter(Boolean::class.javaObjectType, BooleanObjectTypeAdapter())
    .registerTypeAdapter(Boolean::class.javaPrimitiveType, BooleanPrimitiveTypeAdapter())
    .create()

我还创建了一个gist来保存这些并编写测试。

相关问题