最近在做一个解析json的Android疫情数据项目时遇到了这个问题,如何解析json并使用数据呢?查了网上常见的几种方式,一般是用原生的JsonObject类和Gson类或者是其他框架,这里仅记录其中的两种方式。
Json主要结构
首先介绍json的数据结构有两种:json对象
和json数组
json对象
在一个json中,对象结构是使用大括号“{}”括起来的,大括号内是由0个或多个用英文逗号分隔的“关键字:值”对(key:value)构成的。
例如:
1 2 3 4 5 6
| { "键名1":值1, "键名2":值2, …… "键名n":值n
|
1 2 3 4 5 6 7 8 9
| { "string1": "123456", "string2": "一二三四五六", "string3": "hello world" "string4": { "a": "b", "c": "d" } }
|
json数组
JSON数组结构是用中括号“[]”括起来,中括号内部由0个或多个以英文逗号“,”分隔的值列表组成。
例如:
1 2 3 4 5 6 7 8 9 10
| { "string1": "123456", "string2": "一二三四五六", "string3": "hello world" "array1": [ 1, 2, 3 ] }
|
其中的array1就是一个json数组。
通常情况下,复杂的json都是这两种结构互相嵌套的。
到这里,应该就能懂得基本的json知识了。
使用JSONObject解析(复杂)
首先是提供的原生的工具类有:
- JSONObject: Json对象,可以完成Json字符串与Java对象的相互转换
- JSONArray: Json数组,可以完成Json字符串与Java集合或对象的相互转换
- JSONStringer: Json文本构建类,这个类可以帮助快速和便捷的创建JSON text, 每个JSONStringer实体只能对应创建一个JSON text
- JSONTokener:Json解析类
- JSONException:Json异常
通过以上的工具类提供的方法,当想要取到某个值时,就要根据具体的json格式来一层一层解析,就能获取数值。
解析json对象
例如:
1 2 3 4 5 6
| { "id":2, "\"name\":\"金鱼\", "\price\":12.3 }
|
解析:
1 2 3 4 5 6 7 8 9 10 11 12 13
| try { JSONObject jsonObject = new JSONObject(json);
int id1 = jsonObject.optInt("id"); String name = jsonObject.optString("name");
double price = jsonObject.optDouble("price");
} catch (JSONException e) { e.printStackTrace();
|
注意:在方法optString("xxx",null)中,xxx必须与json对象名完全一致,否则会解析失败,即取不到值。至于为什么不用getString(),这是因为optString()会在得不到值时候返回空字符串"",而getString则会抛出异常(直接崩溃)。
解析json数组
例如:
1 2 3 4 5 6 7
| [{ "id":2, "\"name\":\"金鱼\", "\price\":12.3 }]
|
解析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| try { JSONArray jsonArray = new JSONArray(json); for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); if (jsonObject != null) { int id = jsonObject.optInt("id"); String name = jsonObject.optString("name"); double price = jsonObject.optDouble("price"); } } } catch (JSONException e) { e.printStackTrace();
|
一个例子
这是一段比较复杂的json,其中还嵌套了一个数组,截取其一段json如下:
1 2 3 4 5 6 7 8 9 10
| {"ret":0, "data": "{\"lastUpdateTime\":\"2021-05-26 16:59:06\", \"chinaTotal\":{\"confirm\":108999,\"heal\":98805,\"dead\":4892}, \"chinaAdd\":{\"confirm\":1191,\"heal\":16,\"dead\":17,\"nowConfirm\":1159} \"areaTree\":[{\"name\":\"中国\", \"today\":{\"confirm\":1191,\"isUpdated\":true}, \"total\":{\"nowConfirm\":5302,\"confirm\":108999,\"suspect\":2,\"dead\":4892}, ...... }]}}
|
例如:若想要取到其中"lastUpdateTime"
、heal:98805"
、today下的"confirm"
这三个值。
分析:前面两个值在字符串中,后面一个值在以areaTree为名的数组中。
解析方式为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| try{ JSONObject jsonObjectALL = new JSONObject(jsonData); String data = jsonObjectALL.optString("data",null); JSONObject jsonObject = new JSONObject(data); String lastUpdateTime = jsonObject.optString("lastUpdateTime",null); String chinaTotal_now = jsonObject.optString("chinaTotal",null); JSONObject chinaTotal = new JSONObject(chinaTotal_now); String confirmNum = chinaTotal.optString("confirm",null); String healNum = chinaTotal.optString("heal",null); String deadNum = chinaTotal.optString("dead",null); ...... }catch (JSONException e) { e.printStackTrace(); }
|
由此看来,对于非常复杂的json,想要取到某个想要的值,首先就得观察好它的位置,然后一层一层解析包含它的字符串或是数组才行。
这种方法显然过于复杂了,代码也不够简洁,不过对于初学者也够用了
使用Gson解析json
使用之前,需要先将这个包添加到gradle
1
| implementation 'com.google.code.gson:gson:2.8.1'
|
json转对象:
1
| new Gson().fromJson(String json, Class<T> classOfT)
|
首先要建立一个InfoBean类用来解析json,注意定义的变量名必须与json中数据的key值相同,然后自动生成getter和setter即可,可以根据需要的数据来定义,非常灵活。也可以使用一些在线解析json的网站。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class InfoBean { private int confirm; private int Dead; private int Heal; public int getConfirm() {return confirm;}
public void setConfirm(int confirm) { this.confirm = confirm;}
public int getDead() {return dead;}
public void setDead(int dead) {this.dead = dead;}
public int getHeal() {return heal;}
public void setHeal(int heal) {this.heal = heal;}
|
例子
对于这个数组:
1 2 3 4 5 6 7
| [{ "id":2, "\"name\":\"金鱼\", "\price\":12.3 }]
|
解析如下:
1 2 3 4 5 6 7
| Gson gson = new Gson(); List<ShopInfo> shops = gson.fromJson(json, new TypeToken<List<ShopInfo>>() { }.getType()); // 展示数据 tv_gson_last.setText(shops.toString());
|
参考文章
本文部分内容参考了以下文章:
(1) Android项目之JSON解析(3种解析技术详解)_ChessLuo-CSDN博客_安卓json解析方法
(2) Android GSON使用_Android唐浮的专栏-CSDN博客_android gson
(3)JSON 数据结构、数据格式_Hern(宋兆恒)-CSDN博客_json数据结构