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

Posted

技术标签:

【中文标题】Java Parse Json 与具有不同对象类型(Gson 或 Jackson 等)的数组【英文标题】:Java Parse Json with array with different object types (Gson or Jackson or etc.) 【发布时间】:2018-01-20 04:43:20 【问题描述】:
 
   "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 对这些动态索引数据进行映射呢?

感谢您的帮助。

【问题讨论】:

【参考方案1】:

您可以使用自定义反序列化程序。下面的例子是使用 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 -> Data 对象列表),但您可以更改反序列化器,使键 (333) 成为 Data 对象的变量之一,并在 for 循环中分配它。

【讨论】:

以上是关于Java Parse Json 与具有不同对象类型(Gson 或 Jackson 等)的数组的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript浅拷贝与深拷贝以及对象与JSON格式的转换JSON.stringifyJSON.parse

Java - JSON 之 parse & parseObject & parseArray 区别

`JSON.parse(JSON.stringfy())`进行深拷贝方法小结

将java对象转换为具有不同对象名称的json

JSON转换为Java中具有类型属性的XML

如何解析具有相同键的不同数据类型的改造对象的json数组