JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式
数据标记,存储,传输
读写速度快
解析简单
轻量级
独立于语言、平台
具有自我描叙性
“名称/值”对的集合(A collection of name/value pairs)不同的语言中,它被理解为对象(object),纪录(record),
结构(struct)、字典(dictionary)、哈希表(hash table),、有键列表(keyed list) 或者 关联数组(associative array)。
值的有序列表(An ordered list of values)在大部分语言中,它被理解为数组(array)这些都是常见的数据结构,
事实上大部分现代计算机语言都以某种形式支持它们。这使得一种数据格式 在同样基于这些结构的编程语言之间交换成为可能。
是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。
每个“名称”后 跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。

- {
- "name":"英语",
- "score": 80
- }
是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用 “,”(逗号)分隔。

- "courses" : [
- {
- "name":"英语",
- "score": 80
- },
- {
- "name":"数学",
- "score": 90
- }
- ]
可为双引号括起来的字符串(String),数值,true/false,null, 对象(object)或者数组(array)。这些结构可以嵌套。

- {
- "url": "https://qqe2.com",
- "name": "欢迎使用JSON在线解析编辑器",
- "array": {
- "JSON校验": "http://jsonlint.qqe2.com/",
- "Cron生成": "http://cron.qqe2.com/",
- "JS加密解密": "http://edit.qqe2.com/"
- },
- "boolean": true,
- "null": null,
- "number": 123,
- "object": {
- "a": "b",
- "c": "d",
- "e": "f"
- }
- }
-
-
是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义。一个字符(character)即一个单独的字符串(character string);

- {
- "name" : "Zero",
- }
与C或者Java的数值非常相似。除去未曾使用的八进制与十六进制格式。除去一些编码细节。

- {
- "age" : 28
- }
解析原理:基于文档驱动,需要把全部文件读入到内存中,然后遍历所有数据,根据需要检索想要 的数据
具体使用(Android Studio自带)

1>生成JSON
- //生成JSON
- private void createJson(Context context) throws Exception {
- File file = new File(getFilesDir(), "orgjson.json");//获取到应用在内部 的私有文件夹下对应的orgjson.json文件
- JSONObject student = new JSONObject();//实例化一个JSONObject对象
- student.put("name", "OrgJson");//对其添加一个数据
- student.put("sax", "男");
- student.put("age", 23);
- JSONObject course1 = new JSONObject();
- course1.put("name", "语文");
- course1.put("score", 98.2f);
- JSONObject course2 = new JSONObject();
- course2.put("name", "数学");
- course2.put("score", 93.2f);
- JSONArray coures = new JSONArray();//实例化一个JSON数组
- coures.put(0, course1);//将course1添加到JSONArray,下标为0
- coures.put(1, course2);
- //然后将JSONArray添加到名为student的JSONObject
- student.put("courses", coures);
- FileOutputStream fos = new FileOutputStream(file);
- fos.write(student.toString().getBytes());
- fos.close();
- Log.i(TAG, "createJson: " + student.toString());
- Toast.makeText(context, "创建成功", Toast.LENGTH_LONG).show();
- }
2>解析JSON
- //解析JSON
- private void parseJson(Context context) throws Exception {
- File file = new File(getFilesDir(), "orgjson.json");
- FileInputStream fis = new FileInputStream(file);
- InputStreamReader isr = new InputStreamReader(fis);
- BufferedReader br = new BufferedReader(isr);
- String line;
- StringBuffer sb = new StringBuffer();
- while (null != (line = br.readLine())) {
- sb.append(line);
- }
- fis.close();
- isr.close();
- br.close();
- Student student = new Student();
- //利用JSONObject进行解析
- JSONObject stuJsonObject = new JSONObject(sb.toString());
- //为什么不用getString?
- //optString会在得不到你想要的值时候返回空字符串"",而getString会抛出异常
- String name = stuJsonObject.optString("name", "");
- student.setName(name);
- student.setSax(stuJsonObject.optString("sax", "男"));
- student.setAge(stuJsonObject.optInt("age", 18));
- //获取数组数据
- JSONArray couresJson = stuJsonObject.optJSONArray("courses");
- for (int i = 0; i < couresJson.length(); i++) {
- JSONObject courseJsonObject = couresJson.getJSONObject(i);
- Course course = new Course();
- course.setName(courseJsonObject.optString("name", ""));
- course.setScore((float) courseJsonObject.optDouble("score", 0));
- student.addCourse(course);
- }
- Log.i(TAG, "parseJson: " + student);
- Toast.makeText(context, "解析成功", Toast.LENGTH_LONG).show();
- }
-
-
解析原理:基于事件驱动;
解析流程:根据所需取的数据 建立1个对应于JSON数据的JavaBean类,即可通过简单操作解析出所需数据;
Gson 不要求JavaBean类里面的属性一定全部和JSON数据里的所有key相同,可以按需取数据;
具体实现
1.创建一个与JSON数据对应的JavaBean类(用作存储需要解析的数据)
JSON的大括号对应一个对象
对象里面有key,value
JavaBean的类属性名 = key
JSON的方括号对应一个数组
JavaBean里面对应的也是数组
对象里 可以有值/对象
若对象里面只有值,没有key,则说明是纯数组,对应JavaBean里的数组类型
若对象里面有值和key,则说明是对象数组,对应JavaBean里的内部类
对象嵌套
建立内部类 该内部类对象的名字 = 父对象的key ,类似对象数组
- {
- "key": "value",
- "simpleArray": [1,2,3],
- "arrays": [
- [{
- "arrInnerClsKey": "arrInnerClsValue",
- "arrInnerClsKeyNub": 1
- }]
- ],
- "innerclass": {
- "name": "zero",
- "age": 25,
- "sax": "男"
- }
- }
- public class GsonBean {
- private String key;
- private int[] simpleArray;
- private List<ArrayInnerclass> arrays;
- private Innerclass innerclass;
-
-
- public String getKey() {
- return key == null ? "" : key;
- }
-
-
- public void setKey(String key) {
- this.key = key;
- }
-
-
- public int[] getSimpleArray() {
- return simpleArray;
- }
-
-
- public void setSimpleArray(int[] simpleArray) {
- this.simpleArray = simpleArray;
- }
-
-
- public List<ArrayInnerclass> getArrays() {
- if (arrays == null) {
- return new ArrayList<>();
- }
- return arrays;
- }
-
-
- public void setArrays(List
arrays ) { - this.arrays = arrays;
- }
-
-
- public Innerclass getInnerclass() {
- return innerclass;
- }
-
-
- public void setInnerclass(Innerclass innerclass) {
- this.innerclass = innerclass;
- }
-
-
- private static class Innerclass{
- private String name;
- private String sax;
- private int age;
-
-
- public String getName() {
- return name == null ? "" : name;
- }
-
-
- public void setName(String name) {
- this.name = name;
- }
-
-
- public String getSax() {
- return sax == null ? "" : sax;
- }
-
-
- public void setSax(String sax) {
- this.sax = sax;
- }
-
-
- public int getAge() {
- return age;
- }
-
-
- public void setAge(int age) {
- this.age = age;
- }
- }
- private static class ArrayInnerclass{
- private String arrInnerClsKey;
- private int arrInnerClsKeyNub;
-
-
- public String getArrInnerClsKey() {
- return arrInnerClsKey == null ? "" : arrInnerClsKey;
- }
-
-
- public void setArrInnerClsKey(String arrInnerClsKey) {
- this.arrInnerClsKey = arrInnerClsKey;
- }
-
-
- public int getArrInnerClsKeyNub() {
- return arrInnerClsKeyNub;
- }
-
-
- public void setArrInnerClsKeyNub(int arrInnerClsKeyNub) {
- this.arrInnerClsKeyNub = arrInnerClsKeyNub;
- }
- }
- }
在这个序列化和反序列化的过程中, 充当的了一个解析器的角色

0) 解析过程
编写一个Json解析器实际上就是一个方法,它的输入是一个表示JSON的字符串,输出是结构化的对应到语言本身的数据结构
一般来说,解析过程包括 词法分析 和 语法分析两个阶段:

*1.词法分析

- BEGIN_OBJECT({)
- END_OBJECT(})
- BEGIN_ARRAY([)
- END_ARRAY(])
- NULL(null)
- NUMBER(数字)
- STRING(字符串)
- BOOLEAN(true/false)
- SEP_COLON(:)
- SEP_COMMA(,)
*2.语法分析

n ➔ null
t ➔ true
f ➔ false
" ➔ string
0-9/- ➔ number
[ ➔ array
{ ➔ object
1) JsonElement
该类是一个抽象类,代表着json串的某一个元素。这个元素可以是一个Json(JsonObject)、可以是一个 数组(JsonArray)、可以是一个Java的基本类型(JsonPrimitive)、当然也可以为 null(JsonNull);JsonObject,JsonArray,JsonPrimitive,JsonNull都是JsonElement这个抽象类的子类。 JsonElement提供了一系列的方法来判断当前的JsonElement 各个JsonElement的关系可以用如下图表示:

JsonObject对象可以看成 name/values的集合,而这写values就是一个个JsonElement,他们的结构可以
用如下图表示:

2) JsonDeserializer原理


3) TypeAdapter的原理


JSON适配器模式


read 将json->bean write 将bean 转为 json

4) Gson的整体解析原理


TypeToken :获取gson T 的类型
5) Gson的反射解析机制

6) Gson解析常见的错误
Expected BEGIN_ARRAY but was STRING at line 1 column 27
这种错误一般都是原来是一个字段需要是数组类型,但是事实上给的是””,导致的
-解决办法
1. 让返回null即可解决问题
2. 用Gson自带的解决方案