用于原始类型和数组的 GSON 自定义反序列化器

GSON Custom Deserializer for a primitive type and an array

我有一个 JSON 响应可能有不同的值。

"values": [
                    {
                        "type": "AAA",
                        "value": 3
                    },
                    {
                        "type": "BBB",
                        "value": [
                            {
                                "ABC": 8
                            },
                            {
                                "DEF": 9
                            },
                            {
                                "GHI": 9
                            },
                            {
                                "JKL": 8
                            },
                            {
                                "MNO": 9
                            },
                            {
                                "PQR": 9
                            }
                        ]
                    }
                ]

数据Class

data class Values(
    @SerializedName("type")
    @Expose
    val type: String,
    @SerializedName("value")
    @Expose
    val value: Int)

如您所见,value 可以是 Int 或另一个 Json 数组。任何想法如何为此编写反序列化器? Android 应用程序当前正在使用 Int 字段(类型 AAA),我正在尝试集成潜在的数组值(类型 BBB)。谢谢。

试试这个代码:

        try {
            JSONObject jsonObject = new JSONObject(); // this is your values object
            Object o = jsonObject.get("value");
            if (o instanceof JSONArray) {
                //this is jsonarray
            } else if (o instanceof JSONObject) {
                //this is jsonobject
            } else if (o instanceof Integer) {
                //this is int
            } else if (o instanceof String) {
                //this is String
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

首先,在你的情况下使用手动解析而不是自动解析,因为自动解析可能会出现问题并且在这种情况下也有点复杂。现在您需要将请求更改为“JsonObject”。

试试这个代码...

try {
        JSONObject your_response=new JSONObject();

        JSONArray jsonArrayMain=your_response.getJSONArray("values");

        for (int i = 0; i < jsonArrayMain.length(); i++) {
            JSONObject jsonObject=jsonArrayMain.getJSONObject(i);
            String type=jsonObject.getString("type");

            Object o = jsonObject.get("value");
            if (o instanceof JSONArray) {
                //value is array
                JSONArray jsonArrayValue=jsonObject.getJSONArray("value");

                for (int j = 0; j <jsonArrayValue.length(); j++) {

                    JSONObject subJsonObject=jsonArrayValue.getJSONObject(j);
                    
                    Iterator<String> iterator = subJsonObject.keys();
                    while (iterator.hasNext()) {
                        String key = iterator.next();
                        Log.i("====TAG","key:"+key +"--Value::"+subJsonObject.optString(key);
                    }
                }

            } else if (o instanceof String) {
                //value is string
                String value=jsonObject.getString("value");
            }
        }

    }catch (Exception e){
        e.printStackTrace();
    }

希望,它有效。 :)

例如,你可以有一个密封的 class Value 和两个子 classes:

sealed class Value {
    /* type AAA */
    data class IntValue(val value: Int) : Value()
    /* type BBB */
    data class IntPairValue(val value: List<Pair<String, Int>>) : Value() 
}

并编写自定义解串器:

class ValueTypeDeserializer : JsonDeserializer<Value?> {
    override fun deserialize(
        json: JsonElement,
        typeOfT: Type,
        context: JsonDeserializationContext
    ): Value? {
        return when {
            json.isJsonPrimitive -> {
                Value.IntValue(json.asJsonPrimitive.asInt)
            }
            json.isJsonArray -> {
                val list = context.deserialize<List<Map<String, Int>>>(json, LIST_OF_MAP_TYPE)
                val pairs = list.map { e -> e.firstNotNullOf { (key, value) -> Pair(key, value) } }
                Value.IntPairValue(pairs)
            }
            else -> null
        }
    }

    companion object {
        private val LIST_OF_MAP_TYPE = object : TypeToken<List<Map<String, Int>>>() {}.type
    }
}

现在您可以使用 @JsonAdapter 注释将此反序列化器应用于 "value" 字段,例如:

data class Values(
    @SerializedName("type")
    @Expose
    val type: String,
    @SerializedName("value")
    @Expose
    @JsonAdapter(ValueTypeDeserializer::class)
    val value: Value
) {
    val optIntValue: Int?
        get() = (value as? Value.IntValue)?.value
    val optIntPairValue: List<Pair<String, Int>>?
        get() = (value as? Value.IntPairValue)?.value
}

使用 optIntValueoptIntPairValue 访问您感兴趣的值。