用于原始类型和数组的 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
}
使用 optIntValue
或 optIntPairValue
访问您感兴趣的值。
我有一个 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
}
使用 optIntValue
或 optIntPairValue
访问您感兴趣的值。