JSON array to get any diversion within five strokes of GSON

[Switch] get any JSON array with five strokes GSON    https://www.cnblogs.com/jianyungsun/p/6647203.html

About GSON entry-level use, there is not mentioned, if necessary, you can look at this blog post  "Google Gson to use, achieve mutual conversion Json structure"  , well written, easy to understand.

Why do I write this article? Because the first few nights with friends  xiasuhuei321  explore a bit GSON complex JSON parsing time, the array can not be resolved only in the source data, and even resolve only a part of the array. Discussion twenty minutes, concluded: never used, do not know.

So today specifically studied and found really So Easy! Before want complicated, the process of learning, were found to have five ways to get JSON array of different situations, which is today said five strokes!

First to a presentation before the convention, such as the following JSON:

"muser": [
    {
      "name": "zhangsan",
      "age": "10",
      "phone": "11111",
      "email": "[email protected]"
    },
    ...
]
  • Here "muser", is the name of the array, called the data header against the inside of the field with ambiguous;
  • If there is no header data, it is a pure data call, or a data array;
  • The code used in JsonArray / JsonObject like the familiar classes from all GSON.

Began to exchange blows it!

A first move

There is no data on how pure the head of an array of JSON parsing?

According to the agreement, which is the only one inside the JSON array (JsonArray), and the array has no name, like following like this:

[
  {
    "name": "zhangsan",
    "age": "10",
    "phone": "11111",
    "email": "[email protected]"
  },
  {
    "name": "lisi",
    "age": "20",
    "phone": "22222",
    "email": "[email protected]"
  },
  ...
]

In fact, here is the simplest kind of JSON array format, powerful GSON can be resolved directly into a List. But here I will not be directly resolved to use more honest approach to resolve, because of the need leads to two things.

First we need to create a Bean object, note that the variable name field to keep the same name, nothing to say:

public class UserBean {
    //变量名跟JSON数据的字段名需要一致
    private String name ;
    private String age;
    private String phone;
    private String email;
    ...
}

Below this is the resolution process, look at the code:

/**
 * 解析没有数据头的纯数组
 */
private void parseNoHeaderJArray() {
    //拿到本地JSON 并转成String
    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_1);

    //Json的解析类对象
    JsonParser parser = new JsonParser();
    //将JSON的String 转成一个JsonArray对象
    JsonArray jsonArray = parser.parse(strByJson).getAsJsonArray();

    Gson gson = new Gson();
    ArrayList<UserBean> userBeanList = new ArrayList<>();

    //加强for循环遍历JsonArray
    for (JsonElement user : jsonArray) {
        //使用GSON,直接转成Bean对象
        UserBean userBean = gson.fromJson(user, UserBean.class);
        userBeanList.add(userBean);
    }
    mainLView.setAdapter(new UserAdapter(this, userBeanList));
}

As can be seen from the code Step resolved as follows:

  • Whether JSON from a local or network acquisition, should first turn into JSON String;
  • Need a JSON parsing JSON string class object will turn into JsonArray, provided that we know only pure JSON array;
  • Loop through JsonArray, and for analyzing GSON to the corresponding object.

The code itself is not difficult, easy to understand, but said before, I deliberately write here, because of the need to say two things:

1 JsonParse

We can see from the name, this is an analytic category. Yes, it can JSON data respectively getAsJsonObject and getAsJsonArray resolved into JsonObject and JsonArray. This is almost like an ordinary parsing JSON, not unfold said.

2 JsonElement

This class is the first time I see that it is an abstract class that represents the JSON string of one element may be any element JsonObject / JsonArray / JsonPrimitive / ... of.

So in the above code, we can see that it can JsonArray each element turn into JsonObject, or even that it itself is JsonObject.

Well, just to say two things. Remember, it will be used later.

Look at the map to run it, very simple things, two or three are behind this effect, the map will not repeat:

The second measure Q

There are an array of pure data head how to resolve?

JSON exactly the same content with the above, but add a name "muser", which is a good agreement header:

{
  "muser": [
    {
      "name": "zhangsan",
      "age": "10",
      "phone": "11111",
      "email": "[email protected]"
    },
    {
      "name": "lisi",
      "age": "20",
      "phone": "22222",
      "email": "[email protected]"
    },
    ...
  ]
}

Some people say that this is not simple, getAsJsonArray the first one in adding a string that is slightly, like this:

JsonArray jsonArray = parser.parse(strByJson).getAsJsonArray("muser");

The idea is correct, but do not forget, the number of assembly in a {} in the enclosed JsonObject. Remember the above JsonParse it, it's getAsJsonObject can do this, so the code is such a matter, it is no longer easy to explain:

/**
 * 解析有数据头的纯数组
 */
private void parseHaveHeaderJArray() {
    //拿到本地JSON 并转成String
    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_2);

    //先转JsonObject
    JsonObject jsonObject = new JsonParser().parse(strByJson).getAsJsonObject();
    //再转JsonArray 加上数据头
    JsonArray jsonArray = jsonObject.getAsJsonArray("muser");

    Gson gson = new Gson();
    ArrayList<UserBean> userBeanList = new ArrayList<>();

    //循环遍历
    for (JsonElement user : jsonArray) {
        //通过反射 得到UserBean.class
        UserBean userBean = gson.fromJson(user, new TypeToken<UserBean>() {}.getType());
        userBeanList.add(userBean);
    }
    mainLView.setAdapter(new UserAdapter(this, userBeanList));
}

Note that this raises a thing: TypeToken, what is it?

3、TypeToken

This thing is very interesting, I did not know to be doing it, looked at the source code, can not read. Later, I discover it in the package:

import com.google.gson.reflect.TypeToken;

Oh I went to, reflect that this is not reflected it, and it would understand. Yes, it is actually an anonymous inner class, look at the official explanation:

GSON provides TypeToken this class to help us capture (capture) List generic information like this. Java compiler will capture generic information compiled into anonymous inner classes, and then can be getType () method extracts the API reflection at runtime.

The official explanation was, in fact, is a popular but not rigorous, it will turn into a generic T .class. For example, the above TypeToken through getType (after) is UserBean.class.

Well, at this point the basic groundwork is complete, emphasize once again:

For the above JSON can be directly converted into by GSON List, not too much trouble, I just leads to 3 small knowledge.

The third measure W

There are data on how complex the head of the analysis of it?

Having a simple, foreshadowing also Puwan, take a look at the complexity of it:

{
  "code": 200,
  "msg": "OK",
  "muser": [
    {
      "name": "zhangsan",
      "age": "10",
      "phone": "11111",
      "email": "[email protected]"
    },
    {
      "name": "lisi",
      "age": "20",
      "phone": "22222",
      "email": "[email protected]"
    },
    ...
  ]
}

Here is no longer purely an array of data, there are two fields make up the numbers do not know why used, there is also a header, before using a stupid way to really experience what GSON now the power of it.

According to the first step in the establishment of JSON Bean, Bean note here is that returns all fields, because GSON can resolve directly into the List, so Bean is below, the same accounting places get / set omitted:

/**
 * Created by xiarui on 2016/8/30.
 * 返回所有结果的Bean
 */
public class ResultBean {
    //注意变量名与字段名一致
    private int code;
    private String msg;
    private List<UserBean> muser;

    public class UserBean{
        private String name ;
        private String age;
        private String phone;
        private String email;
        ...
    }
    ...
}

Note that this ResultBean which has a UserBean. Although it first with the second measure above although the same content, but the effect is not the same, it is an object of the List as JsonArray parsed into.

Well, a bit hard to pronounce, directly on the bar code:

/**
 * 有消息头 复杂数据 常规方式
 */
private void parseComplexJArrayByCommon() {
    //拿到Json字符串
    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_3);
    //GSON直接解析成对象
    ResultBean resultBean = new Gson().fromJson(strByJson,ResultBean.class);
    //对象中拿到集合
    List<ResultBean.UserBean> userBeanList = resultBean.getMuser();
    //展示到UI中
    mainLView.setAdapter(new ResultAdapter(this, userBeanList));
}

Yes, that is so four sentences to get the contents of the first two strokes. See GSON powerful it, of course, if someone take things too hard to write only one sentence to say:

mainLView.setAdapter(new ResultAdapter(this,new Gson().fromJson(JsonToStringUtil.getStringByJson(this,R.raw.juser_3),ResultBean.class).getMuser()));

I also have no opinion, but please ourselves a little better, thank you.

The fourth move E

Just want to parse JSON in a certain part of a complex array or an array of content how to do?

Well, to focus, and this is with friends  xiasuhuei321  not discussed out of the situation.

Or the above JSON data, repeated here for the sake of space not posted the code, if I just want to take "muser" this array age (age) is greater than 30-year-old how to do?

OK, first of all of course be resolved, then take from the List. That if I had a million data it? All parsing is not very trouble?

So the idea is a first of two strokes, said: traverse!

OK, you might ask first traversal is not to read ten thousand, yes, or to read ten thousand, but if I put them into the database it? If ten thousand data in only one qualified, do not let me keep ten thousand, and then query the database from it?

Of course, this case is an extreme case, but it illustrates a problem, first of all are not resolved in all cases, if there are ten thousand fields, Bean had to write how long ... terrible.

Now it is about a complete idea, which I learned in the process of thinking:

  • The first point is surely just mentioned traverse, this is well understood, so we need to take this array (JsonArray), then how to get it? Remember JsonParse mentioned it before, it's getAsJsonArray () can get an array of incoming data head, of course, do not forget the outermost layer is a JsonObject.
    //最外层
    JsonObject jsonObject = new JsonParser().parse(strByJson).getAsJsonObject();
    //需要遍历的数组
    JsonArray jsonArray = jsonObject.getAsJsonArray("muser");
  • After get the array, we can iterate, and after the first two strokes of baptism, believe in the traversal, should be no problem, or JsonElement mentioned before use.
    //循环遍历数组
    for (JsonElement user : jsonArray) {
        UserBean userBean = new Gson().fromJson(user, new TypeToken<UserBean>() {}.getType());
        //根据条件过滤
        if (Integer.parseInt(userBean.getAge()) > 30) {
            userBeanList.add(userBean);
        }
    }
  • The above code is very simple, also used TypeToken previously mentioned, would not explain what the meaning of it.

Well, the complete code is as follows:

/**
 * 有数据头 复杂数据 截取方式
 */
private void parseComplexJArrayByDirect() {
    //拿到JSON字符串
    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_3);
    List<UserBean> userBeanList = new ArrayList<>();

    //拿到数组
    JsonObject jsonObject = new JsonParser().parse(strByJson).getAsJsonObject();
    JsonArray jsonArray = jsonObject.getAsJsonArray("muser");

    //循环遍历数组
    for (JsonElement user : jsonArray) {
        UserBean userBean = new Gson().fromJson(user, new TypeToken<UserBean>() {
        }.getType());
        //根据条件过滤
        if (Integer.parseInt(userBean.getAge()) > 30) {
            userBeanList.add(userBean);
        }
    }
    mainLView.setAdapter(new UserAdapter(this, userBeanList));
}

FIG operation results as follows:

We can see, now we only did it take JSON data in a certain part of the array. Then expand it, take only one array of JSON data in a certain field it? Of course you can achieve, but still leave you to think for themselves, of course against humanity following the fifth trick is to solve this problem.

Fifth strokes R

If a JSON data is very complicated how to resolve?

What is complicated, and here I simply wrote a more complex, there is a header, one nested layer, I have not yet written the array:

{
  "group": {
    "user": {
      "name": "张三",
      "age": "10",
      "phone": "11111",
      "email": "[email protected]"
    },
    "info": {
      "address": "北京",
      "work": "Android Dev",
      "pay": "10K",
      "motto": "先定一个小目标,比如我先赚一个亿"
    }
  }
}

Resolved in three ways:

  • The third measure, all parse it out;
  • The fourth move, what to what resolve;
  • Fifth trick against humanity JsonReader.

As to why crimes against humanity, can not say. We look at the code will know, the code is very simple, with almost XML parsing is based nodes, as to how to use, then again direct look at the code it really deal with clear logic, but on the amount of code, not really dare compliment.

Just paste the code does not explain, If you want to learn more about, see end of text links.

/**
 * 通过JsonReader的方式去解析
 */
private void parseComplexJArrayByReader() throws IOException {
    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_4);
    JsonReader reader = new JsonReader(new StringReader(strByJson));
    try {
        reader.beginObject();
        String tagName = reader.nextName();
        if (tagName.equals("group")) {
            //读group这个节点
            readGroup(reader);
        }
        reader.endObject();
    } finally {
        reader.close();
    }
}

/**
 * 读group这个节点
 *
 * @param reader JsonReader
 */
private void readGroup(JsonReader reader) throws IOException {
    reader.beginObject();
    while (reader.hasNext()) {
        String tagName = reader.nextName();
        if (tagName.equals("user")) {
            readUser(reader);
        } else if (tagName.equals("info")) {
            readInfo(reader);
        }
    }
    reader.endObject();
}

/**
 * 读用户基本消息 user节点
 *
 * @param reader JsonReader
 */
private void readUser(JsonReader reader) throws IOException {
    reader.beginObject();
    while (reader.hasNext()) {
        String tag = reader.nextName();
        if (tag.equals("name")) {
            String name = reader.nextString();
            nameText.setText(name);
        } else if (tag.equals("age")) {
            String age = reader.nextString();
            ageText.setText(age);
        } 
        ...
        else {
            reader.skipValue();//忽略
        }
    }
    reader.endObject();
}

/**
 * 读用户其他消息 info节点
 *
 * @param reader JsonReader
 */
private void readInfo(JsonReader reader) throws IOException {
    reader.beginObject();
    while (reader.hasNext()) {
        String tag = reader.nextName();
        if (tag.equals("address")) {
            String address = reader.nextString();
            addressText.setText(address);
        } else if (tag.equals("work")) {
            String work = reader.nextString();
            workText.setText(work);
        } 
        ...
        else {
            reader.skipValue();//忽略
        }
    }
    reader.endObject();
}

The above code is omitted as long ... run is as follows:

五招过完,多谢指教!

总结

以上几乎就是 JSO N数组的所有情况了,这五招也几乎能全部搞定!不得不说,GSON 确实比较强大,强大在于可以将 JSON 直接解析成对象,比以前的手动去解析方便太多,当然 fastJson 也能实现这点,但是这东西还是官方的用的顺手。

在学习的过程中,也是一步一步来的,所以文章也是学习的过程,从简单的例子学到关键内容,再解决复杂情况。由于文章写得仓促,如有疑问或错误,欢迎交流与指正,谢谢!

Guess you like

Origin blog.csdn.net/Super_Jadroid/article/details/82260258