Java 解析 Json 与具有不同对象类型的数组(Gson 或 Jackson 等)

标签 java android json jackson gson

 {
   "response": {
     "data": {
       "333": [
         {
           "id": "69238",
           "code": "545"
         },
         {
           "id": "69239",
           "code": "545",
           "marked": "123"
         }
       ],
       "544": [
         {
           "id": "69906",
           "code": "544",
           "marked": "123"
         },
         {
           "id": "69907",
           "code": "544"
         }
       ],
       "890": [
         {
           "id": "69238",
           "code": "545",
           "marked": "123"
         },
         {
           "id": "69239",
           "code": "545"
         }
       ]
     }
   }
 }

我有这个 JSON 数据作为响应并尝试映射。不幸的是我不能。

第一个原因是对象的索引是可变的。例如,一个索引为 890,另一个索引为 544。

第二个原因是对象中的项目数不同。

当我尝试使用www.jsonschema2pojo.org创建java类时。我得到很多带有下划线+整数的类。例如;

 import com.google.gson.annotations.Expose;
 import com.google.gson.annotations.SerializedName;
 import org.apache.commons.lang.builder.EqualsBuilder;
 import org.apache.commons.lang.builder.HashCodeBuilder;
 import org.apache.commons.lang.builder.ToStringBuilder;

 public class _544 {

     @SerializedName("id")
     @Expose
     private String id;
     @SerializedName("code")
     @Expose
     private String code;
     @SerializedName("marked")
     @Expose
     private String marked;

     public String getId() {
         return id;
     }

     public void setId(String id) {
         this.id = id;
     }

     public String getCode() {
         return code;
     }

     public void setCode(String code) {
         this.code = code;
     }

     public String getMarked() {
         return marked;
     }

     public void setMarked(String marked) {
         this.marked = marked;
     }

     @Override
     public String toString() {
         return ToStringBuilder.reflectionToString(this);
     }

     @Override
     public int hashCode() {
         return new HashCodeBuilder().append(id).append(code).append(marked).toHashCode();
     }

     @Override
     public boolean equals(Object other) {
         if (other == this) {
             return true;
         }
         if ((other instanceof _544) == false) {
             return false;
         }
         _544 rhs = ((_544) other);
         return new EqualsBuilder().append(id, rhs.id).append(code, rhs.code).append(marked, rhs.marked).isEquals();
     }

 }    

另外一个是这样的

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

public class _890 {

    @SerializedName("id")
    @Expose
    private String id;
    @SerializedName("code")
    @Expose
    private String code;
    @SerializedName("marked")
    @Expose
    private String marked;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMarked() {
        return marked;
    }

    public void setMarked(String marked) {
        this.marked = marked;
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(id).append(code).append(marked).toHashCode();
    }

    @Override
    public boolean equals(Object other) {
        if (other == this) {
            return true;
        }
        if ((other instanceof _890) == false) {
            return false;
        }
        _890 rhs = ((_890) other);
        return new EqualsBuilder().append(id, rhs.id).append(code, rhs.code).append(marked, rhs.marked).isEquals();
    }

}

数字 544 或 890 等是动态的

那么我如何使用 Java 来映射这个动态索引数据呢?

感谢您的帮助。

最佳答案

您可以使用自定义解串器。下面的示例使用 Gson,但使用 Jackson 也可以完成相同的操作。

class CustomDeserializer implements JsonDeserializer<Response> {

    @Override
    public Response deserialize(JsonElement jsonElement, Type typeOfElement, JsonDeserializationContext context) throws JsonParseException {
        JsonObject data = jsonElement.getAsJsonObject().get("response").getAsJsonObject().get("data").getAsJsonObject();
        Type listType = new TypeToken<List<Data>>() {}.getType();
        Map<String, List<Data>> dataMap = new HashMap<String, List<Data>>();

        for (Map.Entry<String, JsonElement> entry : data.entrySet()) {
            List<Data> dataList = context.deserialize(entry.getValue(), listType);

            dataMap.put(entry.getKey(), dataList);
        }

        return new Response(dataMap);
    }
}

在主类中:

String json = "...";

Gson gson = new GsonBuilder().registerTypeAdapter(Response.class, new CustomDeserializer()).create();

System.out.println(gson.fromJson(json, Response.class));

响应类:

class Response {
    private Map<String, List<Data>> data;

    public Response(Map<String, List<Data>> data) {
        this.data = data;
    }
}

每个数据对象的类:

class Data {
    private String id;
    private String code;
    private String mark;
}

此处的响应将包含每个数据条目的映射及其值列表。 (例如:333 -> 数据对象列表),但您可以更改反序列化器,使键 (333) 成为数据对象的变量之一,并在 for 循环中分配它。

关于Java 解析 Json 与具有不同对象类型的数组(Gson 或 Jackson 等),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45639018/

相关文章:

javascript - 是否可以在 JavaScript 中的对象声明内执行循环

json - 选择具有特定键值对但不具有其他键值对的文档

java - 关于 Java 中通配符(泛型)的澄清

android - 如何在不重新安装应用程序的情况下调试它?

android - 我可以在 Android 上开发 Android 应用程序吗?

android - 将Opencv链接到我自己的android项目

Java 安卓开发

java - 使用Azure的java sdk创建VM并标记所有相关资源

java - 引用匿名类?

java - "Unrecognized token ' com ': was expecting (' 真 ', ' 假 ' or ' 空 ')"