如何使用Gson TypeAdapter摆脱价值?

时间:2019-12-09 08:31:22

标签: json kotlin gson

我有一个如下所示的json字符串:

{ "SomeStringProperty": { "value":"StringValue"},
  "SomeIntProperty": { "value": 1},
  "SomeBooleanProperty": {"value": true}
}

如何将其映射到以下对象

data class PoJo(val SomeStringProperty: String,//
 val SomeIntProperty: Int,//
 val SomeBooleanProperty: Boolean)

1 个答案:

答案 0 :(得分:0)

应该为所有可能包装的类型注册TypeAdapterFactory。然后,工厂将委托给实际的适配器。当且仅当json包含一个名为"value"的单个属性时,它才会将此属性值提供给委托。

实现应类似于以下内容。在这里write总是写原始值,而read遵循上面的想法。

class GenericAdapterFactory : TypeAdapterFactory {

    override fun <T> create(gson: Gson, TypeToken<T> type): TypeAdapter<T> {
        val delegateAdapter = gson.getDelegateAdapter(this, type)
        val jsonAdapter = gson.getDelegateAdapter(this, JsonElement::class.java)
        return GenericAdapter<T>(delegateAdapter, jsonAdapter)
    }
}

class GenericAdapter<T>(
    private val delegateAdapter: TypeAdapter<T>,
    private val jsonAdapter: TypeAdapter<JsonElement>
) : TypeAdapter<T> {

    override fun read(reader: JsonReader): T {
        if (reader.peak() != BEGIN_OBJECT)
            return delegateAdapter.read(reader)
        var element = jsonAdapter.read(reader)
        element = with(element.asJsonObject) {
            takeIf { element.entrySet().size == 1 }?.get("value")
        } ?: element
        return delegateAdapter.fromJsonTree(element)
    }

    override fun write(writer: JsonWriter, value: T) {
        delegateAdapter.write(writer, value)
    }
}