在java中使用GSON解析JSON并填充列表视图

时间:2014-10-17 01:03:01

标签: java android json gson

我意识到我的问题已经被问了很多但是我花了相当多的时间来搜索SO和谷歌试图更好地理解这个概念而没有成功。我已经看到了许多不同的实现,这使我得到了一些关于我的具体情况的建议。

我的目标

我需要对php文件执行post请求,目标是最终使用一些json数据填充列表活动中的字段。

HTTP POST响应

以下是我从服务器返回的响应数据的格式,它似乎是数组的JSON对象(?)。

   {"expense":[{"cat_id_PK":237,"cat_name":"Name1","cat_amount":"100.00","is_recurring":0},
   {"cat_id_PK":238,"cat_name":"Name2","cat_amount":"200.00","is_recurring":0},
   {"cat_id_PK":239,"cat_name":"Name3","cat_amount":"300.00","is_recurring":0},
   {"cat_id_PK":240,"cat_name":"Name4","cat_amount":"400.00","is_recurring":0}],
   "expense_rec": [{"cat_id_PK":207,"cat_name":"Name5","cat_amount":"500.00","is_recurring":1}]}

第一个问题

以下代码是我用来阅读回复的内容。这是我应该如何处理的?获取json编码的响应然后将其更改为字符串似乎很奇怪,只是尝试再次访问json对象的元素。我在这里错了吗?

//This code is in the doInBackground method of my "sendPostRequest" async task.
HttpResponse httpResponse = httpClient.execute(httpPost);

InputStream inputStream = httpResponse.getEntity().getContent();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

StringBuilder stringBuilder = new StringBuilder();
String bufferedStrChunk = null;

while ((bufferedStrChunk = bufferedReader.readLine()) != null) {
      stringBuilder.append(bufferedStrChunk);
}
//Returns string to onPostExecute()
return stringBuilder.toString();

第二个问题

我有另一个名为" PostResponse.java"我保留了以下代码,我在线教程后建模。我不确定如何从onPostExecute方法与此类进行交互。我如何访问第一个对象中的第一个项目(在PHP中你可以做的事情:费用[0] [' cat_name'])。我试图以各种方式做到这一点但没有成功。这是PostResponse.java类:

public class PostResponse {
public Integer cat_id_PK;
public String cat_name;
public BigDecimal cat_amount;
public Integer is_recurring;

public int getID() {
    return this.cat_id_PK;
}
public void setID(int cat_id_PK){
    this.cat_id_PK = cat_id_PK;
}

public String getName() {
    return this.cat_name;
}
public void setName(String cat_name) {
    this.cat_name = cat_name;
}

public BigDecimal getAmount() {
    return this.cat_amount;
}
public void setAmount(BigDecimal cat_amount) {
    this.cat_amount = cat_amount;
}

public int getRecurring() {
    return this.is_recurring;
}
public void setRecurring(int is_recurring) {
    this.is_recurring = is_recurring;
}

@Override
public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("*** Categories ***");
    sb.append("cat_id_PK="+getID()+"\n");
    sb.append("cat_name="+getName()+"\n");
    sb.append("cat_amount="+getAmount()+"\n");
    sb.append("is_recurring="+getRecurring()+"\n");

    return sb.toString();
}

}

这是我的onPostExecute方法的内容:

protected void onPostExecute(String result) {
    super.onPostExecute(result);

    Gson gson = new Gson();              
    PostResponse response = gson.fromJson(result, PostResponse.class);
    System.out.println(result);
}

就像我原先说的那样,我的最终目标是将这些项目填充到列表活动中,但此时我只是知道如何获取特定元素。但是,如果有人想在他们的回复中包含如何填充列表活动,那将会让我更加头疼,因为java对我来说并不容易!

4 个答案:

答案 0 :(得分:2)

  

第一个问题

     

以下代码是我用来阅读回复的内容。这是我应该如何处理的?获取json编码的响应然后将其更改为字符串似乎很奇怪,只是尝试再次访问json对象的元素。我在这里错了吗?

这是处理http响应的一种方法。 “json编码响应”只不过是基于文本的响应,因此将其转换为接收端的字符串是有意义的。也就是说,就Java而言,你收到的json不是一个“对象”:它只是一个对象(或你的情况下的一堆对象)的文本表示,作为一个字节流接收。

话虽如此,您可以通过跳过字符串(构建器)部分来缩短代码。 Gson提供了alternative constructor that takes a Reader个实例,您可以为其提供代码段中的BufferedReader

作为旁注:将文本json转换为Java对象是一种潜在的“重”操作。因此,您最好避免在main / ui线程上执行此操作,因此只需将其移至doInBackground()的{​​{1}}方法(并适当更改类型)。

  

第二个问题

     

我有另一个名为“PostResponse.java”的文件,其中包含我在线教程后建模的以下代码。我不确定如何从onPostExecute方法与这个类进行交互。我怎样才能访问第一个对象中的第一个项目(例如在PHP中你可以做的事情:expense [0] ['cat_name'])。我试图以各种方式做到这一点但没有成功。

你很接近,但是如果你仔细观察json样本,你会发现你的AsyncTask类不适合它:

PostResponse

考虑上面更多的分层格式。在第一级有两个(json)对象:{ "expense": [ { "cat_id_PK": 237, "cat_name": "Name1", "cat_amount": "100.00", "is_recurring": 0 }, { "cat_id_PK": 238, "cat_name": "Name2", "cat_amount": "200.00", "is_recurring": 0 }, { "cat_id_PK": 239, "cat_name": "Name3", "cat_amount": "300.00", "is_recurring": 0 }, { "cat_id_PK": 240, "cat_name": "Name4", "cat_amount": "400.00", "is_recurring": 0 } ], "expense_rec": [ { "cat_id_PK": 207, "cat_name": "Name5", "cat_amount": "500.00", "is_recurring": 1 } ] } expense(都包含0 ... *元素,如方括号所示)。这意味着无论你想要将json映射到哪个类,都应该定义这些字段。如果你现在看看你的expense_rec类,很明显,在它当前的形式中它实际上模拟了上述字段中的一个子对象。

基本上,将json映射到的类应该看起来像这样:

PostResponse:

PostResponse

的ExpenseItem:

public class PostResponse {

    public ExpenseItem[] expense;
    public ExpenseItem[] expense_rec; 
    // List<ExpenseItem> is also supported

    // getters & setters
}

定义模型类后,尝试让Gson再次发挥其魔力。如果一切顺利,您应该能够以类似于PHP习惯的方式访问数据:

public class ExpenseItem {

    public Integer cat_id_PK;
    public String cat_name;
    public BigDecimal cat_amount;
    public Integer is_recurring;

    // getters & setters
}

...或// map json to POJOs PostResponse response = new Gson().fromJson(bufferedReader, PostResponse.class); // retrieve the cat_name for the first item (assuming there is one) String catName = response.getExpense()[0].getName(); 中定义的getter的任何其他字段。

一旦你有了这个部分,那么向适配器提供数组或费用列表是相当简单的(看看Android framenwork中的ExpenseItem)并将该适配器绑定到{{ 1}}。

答案 1 :(得分:1)

  1. 答案是肯定的,您将在InputStream中获得响应
  2. 对于您的第二个问题,请查看此问题 - jsonschema2pojo这可以在为您的JSON数据创建模型时提供帮助。
  3. 然后使用GSON

    Gson gson = new Gson(); 
    YourObj yourObj = (YourObj) gson.fromJson(result, YourObj.class);
    

答案 2 :(得分:0)

  1. 答案是肯定的。收到的答复为InputSteam

  2. protected void onPostExecute(String result) {     super.onPostExecute(结果);

    Gson gson = new Gson();              
    PostResponse response = gson.fromJson(result, PostResponse.class);
    System.out.println(result);
    

    }

  3. 此代码部分主要是指在获得Web响应并获取String格式json响应的AsyncTask之后,将使用该Stringfied json调用此onPostExecute

     Gson gson = new Gson();   
    

    Gson是Google支持的一个库,用于将反序列化反序列化到您的类OBject中。

    gson.fromJson(result, PostResponse.class);
    

    这种方法是反序列化的真正过程。 result是Stringfied json,第二个是要反序列化的Target类。 这将返回一个PostResponse对象,您现在可以使用它。

答案 3 :(得分:0)

对于json数据(

{"expense":[{"cat_id_PK":237,"cat_name":"Name1","cat_amount":"100.00","is_recurring":0},
   {"cat_id_PK":238,"cat_name":"Name2","cat_amount":"200.00","is_recurring":0},
   {"cat_id_PK":239,"cat_name":"Name3","cat_amount":"300.00","is_recurring":0},
   {"cat_id_PK":240,"cat_name":"Name4","cat_amount":"400.00","is_recurring":0}],
   "expense_rec": [{"cat_id_PK":207,"cat_name":"Name5","cat_amount":"500.00","is_recurring":1}]}), 

它包含两个不同的数组,一个是&#34;费用&#34;另一个是&#34; expense_rec&#34;。因此,如果要将这些项填充到列表活动中,可以尝试以下方法。

protected void onPostExecute(String result) {
    super.onPostExecute(result);

    JSONObject jsonObject = new JSONObject(builder.toString());
    Log.i(TAG, "jsonObject is : " + jsonObject.toString());

    //this is the first array data 
    JSONArray jsonArray = jsonObject.getJSONArray("expense");
    Log.i(TAG, "Array length is: " + jsonArray.length());

    for(int i = 0; i < jsonArray.length(); i++){
        JSONObject jsoObj = jsonArray.getJSONObject(i);
        String name = jsoObj.getString("cat_name");
        Log.i(TAG, "file name is: " + name);
    }

    //this is the second array data 
    jsonArray = jsonObject.getJSONArray("expense_rec");
    for(int i = 0; i < jsonArray.length(); i++){
        JSONObject jsoObj = jsonArray.getJSONObject(i);
        String name = jsoObj.getString("cat_name");
        Log.i(TAG, "file name is: " + name);
    }
}