Java 使用Gson动态解析JSON字段类型

Java 使用Gson动态解析JSON字段类型,java,json,gson,Java,Json,Gson,我有以下API响应: { "data":{ "categoryFields":[ { "name":"brand", "label":"Marca", "values":[ { "key":53, "value":"Alfa Romeo"

我有以下API响应:

{  
   "data":{  
      "categoryFields":[  
         {  
            "name":"brand",
            "label":"Marca", 
            "values":[  
               {  
                  "key":53,
                  "value":"Alfa Romeo"
               },
               {  
                  "key":55,
                  "value":"Audi"
               }
            ]
         },
         {  
            "name":"year",
            "label":"Año", ,
            "dataType":"select",
            "values":[  
               {  
                  "key":2017,
                  "value":2017
               },
               {  
                  "key":2016,
                  "value":2016
               }
            ]
         },

      ]
   }
}
好的,在第一个
类别字段中,值为:

"key":53 INT,
"value":"Alfa Romeo", STRING
 "key":2017, INT
 "value":2017, INT
在第二个
类别字段中,值为:

"key":53 INT,
"value":"Alfa Romeo", STRING
 "key":2017, INT
 "value":2017, INT
还有另一种类型:

 "key":"string", STRING
 "value":"String", STRING
我需要一个类,可以处理这些类型的数据。比如:

公共类值{
@序列化名称(“键”)
@暴露
私有动态_型密钥;
@序列化名称(“值”)
@暴露
私有动态_型值;
}
我该怎么做?或者有一个Gson函数来帮助我解决这个问题?

解决方案

public class CategoryValueDeserializer implements JsonDeserializer<CategoryValue> {
    @Override
    public CategoryValue deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

        final JsonObject jsonObject = json.getAsJsonObject();

        final JsonElement jsonKey = jsonObject.get("key");
        final String key = jsonKey.getAsString();

        final JsonElement jsonValue = jsonObject.get("value");
        final String value = jsonValue.getAsString();

        CategoryValue categoryValue = new CategoryValue();
        categoryValue.setKey(key);
        categoryValue.setValue(value);

        return categoryValue;

    }
}

这里有一个可行的解决方案

首先创建一个POJO类,如下所示

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class KeyValuePair {
    @SerializedName("key")
    @Expose
    private String key;
    @SerializedName("value")
    @Expose
    private Object value;

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }
}
然后,为了让Gson正确地序列化这个类,请使用以下代码

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;

import java.lang.reflect.Type;

public class KeyValuePairDeserializer implements JsonDeserializer<KeyValuePair> {
    @Override
    public KeyValuePair deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

        final JsonObject jsonObject = json.getAsJsonObject();

        final JsonElement jsonKey = jsonObject.get("key");
        final String key = jsonKey.getAsString();

        final JsonElement jsonValue = jsonObject.get("value");
        Object value = jsonValue.getAsString();
        if (jsonValue.isJsonPrimitive()) {
            JsonPrimitive jsonPrimitive = jsonValue.getAsJsonPrimitive();
            if (jsonPrimitive.isBoolean())
                value = jsonValue.getAsBoolean();
            else if (jsonPrimitive.isString())
                value = jsonValue.getAsString();
            else if (jsonPrimitive.isNumber()){
                value = jsonValue.getAsNumber();
            }
        }
        KeyValuePair categoryValue = new KeyValuePair();
        categoryValue.setKey(key);
        categoryValue.setValue(value);
        return categoryValue;
    }
}
现在您可以使用如下getter方法访问这些值

public String getString(String key) {
    return (String) value;
}

public int getInt(String key) {
    return ((Number) value).intValue();
}

public long getLong(String key) {
    return ((Number) value).longValue();
}

public float getFloat(String key) {
    return ((Number) value).floatValue();
}

public boolean getBoolean(String key) {
    return (boolean) value;
}

我总是有BE提供的类似于
数据类型的东西。然后我可以在反序列化过程中基于它的值。您也有
dataType
,但只适用于
Int,Int
case

嗯,我会做两件事中的一件:

  • 与BE交谈,针对每个不同的情况发送不同的
    数据类型。这适用于具有许多参数且只有少数不同数据类型的类型。然后,我使用
    JsonDeserializer
    反序列化到我需要的内容,有条件地-基于
    dataType
  • 如果您只有两个值和三种可能的情况,那么很容易通过
    isString
    和其他方法进行检查,正如在不同的答案中所建议的那样