JSON、GSON 骑猪看日落 2022-04-13 04:19 261阅读 0赞 ### 文章目录 ### * * 什么是JSON * 特点 * JSON的数据结构 -- Object * JSON的数据结构 -- Array * JSON的数据结构 -- 基本类型 * 构建 JSON 数据 * 解析 JSON 数据 * GSON * 构建 GSON * 解析 GSON * 对比 JSON 的强大之处 -------------------- ## 什么是JSON ## **`JSON(JavaScript Object Notation)`** 是一种与开发语言无关的、轻量级的 **数据格式**;重点记住,它是一种数据格式 ; -------------------- ## 特点 ## 非常易于人的阅读和编写,同时也很容易被程序解析 ; -------------------- ## JSON的数据结构 – Object ## 使用花括号 `{}` 括起来的键值对结构,其中 `key` 必须是 `String` 类型,`value` 为 **`任何`** **基本类型** 或 **数据结构** ; 其中键值对内部使用冒号 `:` 连接, 键值对之间使用逗号 `,` 连接 ; -------------------- ## JSON的数据结构 – Array ## 使用中括号 `[]` 括起来,元素之间使用逗号 `,` 分隔 ; 元素也是可以为 **`任何`** 类型 ; -------------------- ## JSON的数据结构 – 基本类型 ## JSON 的基本类型有 **`5`** 种: * `string` 代表字符串 ,字符串需要用双引号 `" "` 括起来 ; * `number` 数值类型,`JSON` 中只有一个 `number` 类型,是没有 `int float double` 这些类型的 ; * `true/false` 布尔类型 * `null` `JSON` 中也定义了一个代表 **`空`** 的关键字 ; 可以看见 `JSON` 好多的格式,都不支持,比如 **`日期`** 类型,这也是 `JSON` 的一个缺点,下面介绍的 `GSON` 弥补了这一缺点 ; -------------------- ## 构建 JSON 数据 ## 1. 使用 **`JSONObject`** 对象构建 `JSON` 数据 @Test public void object2Json(){ // 定义一个 null 对象 ; Object NULL = null ; // 利用 jsonObject 对象,构建 JSON JSONObject jsonObject = new JSONObject() ; jsonObject.put("name","yaz") ; jsonObject.put("sex","男") ; // 日期类型,用字符串,JSON 里面没有日期类型 jsonObject.put("birthday","1997-01-22") ; // 插入数字的时候,java的数值类型,最后都会被转为 JSON 的number 类型 jsonObject.put("salary",5000.00) ; jsonObject.put("age",22) ; jsonObject.put("hasHouse",false) ; // 直接传入 null ,编译不通过,因为 put 重载了 Collection 和 map 集合 ; // 直接传入 null ,就不知道具体调用哪一个了 // 定义一个 null 对象,绕过编译 ; // 值为 null 的属性,不会被传入到 JSON 中 ; jsonObject.put("hasDream",NULL) ; jsonObject.put("habit",new String[]{ "LOL","打乒乓球","java-IT"}) ; System.out.println(jsonObject.toString()); } 生成的 **`JSON`** 字符串 : { "birthday": "1997-01-22", "sex": "男", "habit": [ "LOL", "打乒乓球", "java-IT" ], "hasHouse": false, "age": 22, "name": "yaz", "salary": 5000 } 2. 使用 **`Map`** 对象构建 `JSON` 数据 @Test public void map2Json(){ Map<String,Object> map = new HashMap<>(); map.put("name","yaz") ; map.put("age",22) ; map.put("birthday","97-01-22") ; map.put("salary",5000.1) ; map.put("habit",new String[]{ "LOL","Music","sleep"}) ; map.put("hasHouse",false) ; map.put("car",null) ; // 还是需要 JSONObject ,将 map 传入 JSONObject jsonObject = new JSONObject(map) ; System.out.println(jsonObject); } 生成的 **`JSON`** 字符串 : { "birthday": "97-01-22", "habit": [ "LOL", "Music", "sleep" ], "hasHouse": false, "name": "yaz", "age": 22, "salary": 5000.1 } 3. 使用 **`Javabean`** 对象构建 `JSON` 数据 **(推荐使用)** @Test public void Javabean2Json(){ Customer customer = new Customer() ; customer.setAge(20); customer.setBirtyday("97-02-28"); customer.setCarName(null); customer.setHabit(new String[]{ "lol","java-IT"}); customer.setSalary(5000.1); customer.setHasHouse(false); JSONObject jsonObject = new JSONObject(customer); System.out.println(jsonObject); } 生成的 `JSON` 字符串 : { "birtyday": "97-02-28", "habit": [ "lol", "java-IT" ], "hasHouse": false, "age": 20, "salary": 5000.1 } 总结: 1. 生成 `JSON` 串,都需要 `JSONObject` 对象 ,可以往里面一个一个属性的 `put` ,也可以直接传给它一个 `map` ,或者一个 `Javabean` 对象; 2. 属性为 **`null`** 的属性,是不会为添加到 `JSON` 串中的 ; -------------------- ## 解析 JSON 数据 ## 1. 从文件中读取 `JSON` 2. 解析数组 这里有个缺点:`JSON` 的工具类不能直接解析数组,需要使用 `JSONArray` 类辅助下 ; 3. 判断 `null` 使用 `jsonObject.isNull("键")` 判断对应的属性,是否存在 ; ; @Test public void json2Object() throws IOException { // 获取 json 串所在的文件 File file = new File(this.getClass().getClassLoader().getResource("jsonString.txt").getFile()); // 使用 Apache 的 fileUtils工具,读取文本文件内容,转成字符串 String json = FileUtils.readFileToString(file, "UTF-8"); // 还是使用 JSONObject 对象 JSONObject jsonObject = new JSONObject(json); // 读取 JSON 串的内容 // 判断 是否有 name 属性,如果没有,则不读取; if (!jsonObject.isNull("name")) { System.out.println("name" + jsonObject.getString("name")); } System.out.println("age" + jsonObject.getInt("age")); System.out.println("salary" + jsonObject.getInt("salary")); // 但是读取数组,需要使用另外一个对象 JSONArray jsonArray = jsonObject.getJSONArray("habit"); for (int i = 0; i < jsonArray.length(); i++) { // 需要强转下 String habit = (String) jsonArray.get(i); System.out.println("habit " + i + ":" + habit); } } 这里有个坑:**地址的写法,注意了,之前的写法,一直不好使,最后,直接建立一个资源文件,扔下面,然后访问到了** **总结**:解析 `JSON` 串的时候,需要我们自己一个一个的去获取属性,对于数组属性,还需要强转,因为它不知道里面的具体类型 ; -------------------- ## GSON ## `Google` 的一个开源项目,对 **`JSON`** 进行了增强,比如支持了日期类型; -------------------- ## 构建 GSON ## @Test public void object2Gson() throws ParseException { CustomerWithDate customerWithDate = new CustomerWithDate(); customerWithDate.setAge(22); customerWithDate.setName("yaz"); customerWithDate.setBirtyday(new SimpleDateFormat("yyyy-mm-dd").parse("1997-1-22")); customerWithDate.setHabit(new String[]{ "lol", "java"}); // 这个不会得到构建 customerWithDate.setPassword("sasas"); // 美化输出样式,使用 GsonBuilder GsonBuilder gsonBuilder = new GsonBuilder(); // 进行个性化定制输出,也就是在构建的时候,对字段进行一些设定 gsonBuilder.setFieldNamingStrategy(new FieldNamingStrategy() { @Override public String translateName(Field field) { if ("name".equals(field.getName())){ return "YAZZZZ" ; } return field.getName(); } }) ; gsonBuilder.setPrettyPrinting(); Gson gson = gsonBuilder.create(); System.out.println(gson.toJson(customerWithDate)); } 使用 `Javabean` 或者 `map` 对象 都可以,`toJson` 操作,参数是一个 `object` 类型 ; -------------------- ## 解析 GSON ## 可以解析成自己的对象,而不是像 `JSON` 那样,解析成 **`JSONObject`** 对象 ; @Test public void gson2Object() throws IOException { // 获取 json 串所在的文件 // 地址的写法,注意了,之前的写法,一直不好使,直接建立一个资源文件,扔下面,然后访问到了 File file = new File(this.getClass().getClassLoader().getResource("jsonString.txt").getFile()); // 使用 Apache 的 fileUtils工具,读取文本文件内容,转成字符串 String json = FileUtils.readFileToString(file, "UTF-8"); // 创建一个 支持解析日期 的 gson Gson gson = new GsonBuilder().setDateFormat("yyyy-mm-dd").create() ; CustomerWithDate customerWithDate = gson.fromJson(json,CustomerWithDate.class); System.out.println(customerWithDate); } -------------------- ## 对比 JSON 的强大之处 ## 1. 支持改变生成 `JSON` 的属性名(别名) /** * 设置别名,使用注解 */ @SerializedName("NAME") private String name; 2. 美化输出 // 美化输出样式,使用 GsonBuilder GsonBuilder gsonBuilder = new GsonBuilder() ; // 设置成漂亮的输出 gsonBuilder.setPrettyPrinting(); 3. 在解析的过程中,进行个性化定制 // 进行个性化定制输出,也就是在构建的时候,对字段进行一些设定 gsonBuilder.setFieldNamingStrategy(new FieldNamingStrategy() { @Override public String translateName(Field field) { if ("name".equals(field.getName())){ return "YAZZZZ" ; } return field.getName(); } }) ; 4. 忽略掉某些 `Javabean` 的属性 // 使用关键字 transient 在构建 JSON 的时候,会忽略掉该属性 private transient String password; 5. 支持解析日期 设定日期解析格式 ; // 创建一个 支持解析日期 的 gson Gson gson = new GsonBuilder().setDateFormat("yyyy-mm-dd").create() ; 6. 支持 **`JSON`** **`Array`** 数组到 `java` 集合类的无缝转换 说的是,对于 `JSON` 的 `Array` 数组,我们在 java 里面是可以直接用 **`集合`** 接收的, **`GSON`** 会自动的转换 ;
还没有评论,来说两句吧...