手动解析动态JSON对象的一部分以及Gson反序列化器

时间:2016-07-19 10:59:20

标签: android json retrofit2 gson

我想用动态JSON对象

解析以下JSON响应
{
  "id": 1,
  "last_login": "2016-07-16T12:46:29.621996Z",
  "point_of_sales": [
    {
      "Counter 4": {
        "type": "retail",
        "id": 6
      }
    },
    {
      "Counter 5": {
        "type": "retail",
        "id": 7
      }
    },
    {
      "Counter 6": {
        "type": "retail",
        "id": 8
      }
    }
  ]
}

此处的对象名称位于" point_of_sales "数组是动态的,这使得使用Gson很难解析。这是我到目前为止所尝试过的,

@SerializedName("id")
@Expose
private Integer id;
@SerializedName("last_login")
@Expose
private String lastLogin;
@SerializedName("point_of_sales")
@Expose
private List<Map<String, Counter>> pointOfSales = new ArrayList<Map<String, Counter>>();

.......

getter & setters

专柜课,

@SerializedName("type")
@Expose
private String type;
@SerializedName("id")
@Expose
private Integer id;

.......

getter & setters

按照这个程序,我可以转换对象但不能将它们从地图中提取到pojo类。

 for (Map<String, Counter> objectMap : response.getPointOfSales())
{
// How to extract the Counter pojo data from map list?
}

我也尝试过这种方式,但没有任何作用,

ArrayList<Counter> pojos = new ArrayList<Counter>();
                    try {
                        for (Map<String, Counter> objectMap : result.getPointOfSales()) {
                            Counter pojo = new Counter();
                            for (Map.Entry<String, Counter> property : objectMap.entrySet()) {
                                Method setter = Counter.class.getMethod("set" + property.getKey().substring(0, 1).toUpperCase() + property.getKey().substring(1), property.getValue().getClass());
                                setter.invoke(pojo, property.getValue());
                            }
                            pojos.add(pojo);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    for (Counter pojo : pojos) {
                        Log.e("result", "" + pojo.getId() + " " + pojo.getType());
                    }

有没有办法使用

来解析特定的数组
  1. Gson

  2. 使用决斗解析技术手动解析特定部分并在Gson中解析其余部分?

  3. 我想将动态对象包装成pojo类。

1 个答案:

答案 0 :(得分:1)

你需要两件事。

  1. 您需要对模型类进行一些重构。
  2. 您需要添加一个JsonDeserializer来处理动态解析。
  3. 这是我将如何做到的:

    <强> MainObject.java

    .....
    @SerializedName("point_of_sales")
    SalesPoints mSales Points
    .....
    

    <强> SalesPoints.java

    private List<Counter>mCounters;
    //getter & setters.
    

    <强> Counter.java

    SerializedName("type")
    private String type;
    @SerializedName("id")
    private int id; // use primitives instead of boxed primitives
    private String mCounterString; // maybe you need it.
    

    现在当你运行解析时,你将不得不这样做:

     MainObject object = new GsonBuilder().registerTypeAdapter(SalesPoints.class, new JsonDeserializer< SalesPoints >() {
            @Override
            public SalesPoints deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
                SalesPoints sales = new SalesPoints();
                ArrayList<Counter>counters = new ArrayList<Counter>();
                JsonArray salesJson = json.getAsJsonArray();
                for(JsonElement object : json.getAsJsonArray()) {
                       Iterator<Map.Entry<String,JsonElement>> iterator = object.getAsJsonObject().entrySet().iterator();
                       while (iterator.hasNext())){
                              Map.Entry<String,JsonElement> entry = iterator.next();
                                String counterString = entry.getKey();
                                JsonElement counterObject = 
                                                        entry.getValue();
                                Counter counter = context.deserialize(counterObject, Counter.class);
                                counter.setCounterString(counterString);
                                counters.add(counter);
                            }          
                }
                sales.setCounters(counters);
                return sales;
            }
        }).create().fromJson(theJson);
    

    现在解析MainObject时,它将包含包含所有计数器的SalesPoints

    注意:我可能拼错了一些单词,或者我可能忘记添加一些getAs..方法,因为我没有可能测试代码,但这是要走的路,你可以很容易调试它。

    修改

    对于改造,你需要做这样的事情:

    Gson gson = new GsonBuilder().registerTypeAdapter(SalesPoints.class, new JsonDeserializer< SalesPoints >() {
            @Override
            public SalesPoints deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
                SalesPoints sales = new SalesPoints();
                ArrayList<Counter>counters = new ArrayList<Counter>();
                JsonArray salesJson = json.getAsJsonArray();
                for(JsonElement object : json.getAsJsonArray()) {
                       Iterator<Map.Entry<String,JsonElement>> iterator = object.getAsJsonObject().entrySet().iterator();
                       while (iterator.hasNext())){
                              Map.Entry<String,JsonElement> entry = iterator.next();
                                String counterString = entry.getKey();
                                JsonElement counterObject = 
                                                        entry.getValue();
                                Counter counter = context.deserialize(counterObject, Counter.class);
                                counter.setCounterString(counterString);
                                counters.add(counter);
                            }          
                }
                sales.setCounters(counters);
                return sales;
            }
        }).create();
    
    
    new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(gson))//set remaining things fro your retrofit builder.