自定义布尔反序列化器无法在Gson中工作

时间:2018-05-15 22:13:46

标签: java json kotlin gson

我必须将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?,但成功地将其他自定义反序列化器用于其他类型(例如,用于枚举)。

为什么?

2 个答案:

答案 0 :(得分:2)

您正在为Boolean::class.java boolean注册解串器,而您实际需要的类型Boolean?正在转换为java.lang.Boolean

要获得java.lang.Boolean,您必须使用Boolean::class.javaObjectType进行注册。

您还可以找到所有原始 Java 类型的相同行为。

答案 1 :(得分:0)

受到@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 来保存这些并编写测试。