蓝旭暑期培训Day3——JSON使用与简单解析

JSON是什么

JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。摘自百度百科

  • JSON是一种轻量级(Light-Meight)、基于文本的(Text-Based)、可读的(Human-Readable)格式。
  • JSON 的名称中虽然带有JavaScript,但这是指其语法规则是参考JavaScript对象的,而不是指只能用于JavaScript 语言。
  • 因为JSON本身就是参考JavaScript 对象的规则定义的,其语法与JavaScript定义对象的语法几乎完全相同。
  • JSON格式的创始人声称此格式永远不升级,这就表示这种格式具有长时间的稳定性,10 年前写的文件,10年后也能用,没有任何兼容性问题。

JSON中午官网

JSON的语法规则

JSON的语法规则比较简单,上面也说过与JavaScript的语法相类似,大概有以下几点:

  1. 数组 (Array) 用方括号[]表示。
  2. 对象 (Object) 用大括号{}表示。
  3. 存值方式:键值对 key-value 可以组合成数组和对象。
  4. key 需要放在置于双引号中,value需要分情况。
  5. 值(value)有字符串、数值、布尔值、null、对象和数组。
  6. 并列的数据之间用英文逗号,进行分割隔。

下面看一个JSON字符串的例子

{
    "username":"wubh576",
    "password":"HelloBluemsun",
    "age":21,
    "girlfriend":null,
    "isStudent":true,
    "selectedCourses":[
        "高等数学A-1","Java","信息安全"
    ],
    "coursesGrade":[60,60,60],
    "hisPet":{
        "name":"Chris",
        "variety":"英短银渐层",
        "favoriteFoods":["小鱼干","鸡胸肉","酸奶"]
    },
    "data":{
        "studentNum":2,
        "detail": [{
            "id": 1,
			"name": "贺嘉",
			"age": "19"
            },{
            "id": 2,
			"name": "谭斯艺",
			"age": "19"
            }
        ]
    },
    "status":"success"
}

JSON实际应用

为什么说是简单解析呢?
在交互中,后端同学承担的任务是对前端发来的JSON字符串进行解析,而这个字符串的格式你们可以预先通过接口文档确定好的,它不是一个未知的字符串,而是具有一定格式的,所以不会涉及用for加强循环去解析未知的JSON字符串。

前端同学需要掌握:JSON的解析和生成(JavaScript实现)、JSON 和 JavaScript 的互转
后端同学需要掌握:JSON的解析和生成(Java实现)、JSON 和 Java 对象的互转

需要注意的是,之前后端同学 view层的 jsp 与controller层的 servlet 进行交互是通过form表单的形式,而之后暑期的项目前后端数据是通过JSON字符串进行交互的

GSON——JSON的序列化与反序列化

Gson 是 Google 提供的用来在 Java 对象和 JSON 数据之间进行映射的 Java 类库。可以将一个 JSON 字符串转成一个 Java 对象,或者反过来。
也就是个jar包,maven的Gson下载传送门!讲课用的版本是2.8.6

  1. fromJson() 反序列化
    Gson提供了fromJson()方法来实现从JSON字符串到Java实体的方法。(此处看一下源码)

先来个JSON字符串的解析栗子🌰

package jsondemo;

import com.google.gson.Gson;
import entity.User;

public class JsonToObjectDemo {
    //这是一个main方法,是程序的入口
    public static void main(String[] args) {
        Gson gson = new Gson();
        String jsonString = "{\"userId\":1,\"username\":\"wubh576\",\"password\":\"HelloBluemsun\",\"grade\":\"2019\"}";
        System.out.println(jsonString);
        User user = gson.fromJson(jsonString,User.class);
        System.out.println(user);
    }
}

再来看个栗子🌰

package jsondemo;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import entity.Bluemsun;
import entity.User;

import java.lang.reflect.Type;
import java.util.List;

public class JsonToListDemo {
    //这是一个main方法,是程序的入口
    public static void main(String[] args) {
        String jsonString = "[\n" +
                "    {\n" +
                "        \"username\": \"tom\",\n" +
                "        \"password\": \"123456\"\n" +
                "    },\n" +
                "    {\n" +
                "        \"username\": \"tony\",\n" +
                "        \"password\": \"1234567\"\n" +
                "    }\n" +
                "]";
        Gson gson = new Gson();

        Type type = new TypeToken<List<User>>(){}.getType();    // Type是Java语言中所有类型的公共父接口,在Java泛型与反射中作用比较大,现在仅会用就行
        List<User> userList = gson.fromJson(jsonString,type);
        System.out.println(userList);

        Type type_1 = new TypeToken<List<Bluemsun>>(){}.getType();
        List<Bluemsun> bluemsunList = gson.fromJson(jsonString,type_1);
        System.out.println(bluemsunList);	// 注意:变量名跟JSON数据字段名必须一致,否则无法将JSON字符串反序列化
    }
}

其他解析情况,根据上述两种情况进行相对应的代码修改即可。

  1. toJson() 序列化

栗子🌰将user对象进行序列化为JSON字符串

package jsondemo;

import com.google.gson.Gson;
import entity.User;

public class ObjectToJsonDemo {
    //这是一个main方法,是程序的入口
    public static void main(String[] args) {
        Gson gson = new Gson();
        User user = new User();
        user.setUsername("wubh");
        user.setPassword("123456");
        String jsonString = gson.toJson(user);
        System.out.println(jsonString);
    }
}

栗子🌰序列化对象数组为JSON字符串

package jsondemo;

import com.google.gson.Gson;
import entity.User;

import java.util.ArrayList;
import java.util.List;

public class ListToJsonDemo {
    //这是一个main方法,是程序的入口
    public static void main(String[] args) {
        User user = new User();
        User user1 = new User();
        user.setUsername("hej");
        user.setPassword("123456");
        user1.setUsername("wubh");
        user1.setPassword("123456");
        List<User> userList = new ArrayList<>();
        userList.add(user);
        userList.add(user1);

        Gson gson = new Gson();
        String jsonString = gson.toJson(userList);
        System.out.println(jsonString);
    }
}

到这里呢,咱们已经掌握了通过GSON去进行JSON的序列化及反序列化,大家可以自己写JSON字符串和代码去尝试进行序列化和反序列化。

下面我们就模拟前后端交互来具体的看一下如何使用JSON。

前后端交互JSON实操

先来聊聊如何获取前端传来的JSON字符串
首先我们来看一下前端post请求的ajax的代码(当然只用看就行了,不用会写,咱们是后端!)

<script>
    function send() {
        // 创建对象
        var xhr = new XMLHttpRequest();
        // 设置基本信息
        xhr.open('post', 'http://localhost:8886/');
        // 设置请求头
        xhr.setRequestHeader('Content-Type', 'application/json');
        //设置监听
        xhr.onreadystatechange = function() {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    console.log("success");
                    if (xhr.responseText) {
                        console.log(JSON.parse(xhr.responseText)); //接收后端传过来的数据
                    } else {
                        console.log(xhr.responseXML); //接收后端传来的XML格式的数据
                    }
                }
            }
            // 发送信息
        xhr.send(JSON.stringify({
            studentnum: document.getElementById("studentnum").value,
            password: document.getElementById("psw").value,
        }));
    }
</script>

这段代码是昨天谭然学姐讲课的时候用到的代码,我们来看几个关键的地方。
设置请求头 Content-Type

// 设置请求头
xhr.setRequestHeader('Content-Type', 'application/json');

Content-Type(内容类型),一般是指网页中存在的 Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件,这就是经常看到一些 PHP 网页点击的结果却是下载一个文件或一张图片的原因。
Content-Type 标头告诉客户端实际返回的内容的内容类型。

在这里插入图片描述
Content-Type 分类
在这里插入图片描述
我们要用到的就是:
Content-Type: application/json
它作为响应头比较常见,用来告诉服务端消息主体是序列化后的 JSON 字符串,其中一个好处就是JSON 格式支持比键值对复杂得多的结构化数据。由于 JSON 规范的流行,除了低版本 IE 之外(不要再用IE了)的各大浏览器都原生支持JSON.stringify,服务端语言也都有处理 JSON 的函数,使用非常方便。

如果想有更多了解,请参考菜鸟教程HTTP Content-Type

所以后台接受过来的应该是在request中传过来的JSON数据文件,那么提到文件,就可以联想到我们之前讲过的JavaIO了。我们需要利用JavaIO进行JSON数据文件的读取,进而获得正确的JSON字符串,上代码。

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取前端发来的数据,并进行处理
        StringBuilder stringBuilder = null;
        String jsonString = null;
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(request.getInputStream()));
        stringBuilder = new StringBuilder();
        String str = "";
        while ((str = bufferedReader.readLine()) != null) {
            stringBuilder.append(str);
        }
        // 获取处理好的json字符串
        jsonString = stringBuilder.toString();

        // 利用GSON进行JSON字符串的反序列化
        Gson gson = new Gson();
        User user = gson.fromJson(jsonString, User.class);
        user.setUsername(user.getUsername());
        user.setPassword(user.getPassword());
        System.out.println(user); 
    }

其实原理很简单:就是读入了request请求中的JSON数据文件,然后将其变为字符串就好了。

现在已经能获取到了前端发送过来JSON字符串了,结合前面学过的GSON再将JSON字符串反序列化为Java对象,之后就随你操作啦~

下面我们来看看如何给前端返回JSON数据呢?

之前已经提过了JSON的存值方式是key-value形式的,所以你要去自己封装一个对象并序列化为JSON字符串传给前端。这里,我用到的是之前讲过Java容器中的Map,为什么,因为Map的存值方式也是key-value形式,但是其他的容器类也是可以根据情况进行使用的。

例如,我们想给前端传输这样一个格式的JSON字符串

{
    "msg": "Login success!",
    "data": {
        "username": "wubh2",
        "password": "123456"
    },
    "status": 1
}

根据刚才的思路,继续上代码。

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Gson gson = new Gson();
        User user1 = new User();
        user1.setUsername("wubh2");
        user1.setPassword("123456");
        Map map = new HashMap();
        map.put("msg","Login success!");
        map.put("status",1);
        map.put("data",user1);
        // 先将map处理好后,再调用response.getWriter()
        // 使用JSON将返回数据返回给前端
        PrintWriter out = response.getWriter();
        /**
         * 但是为什么用response呢?而不是new一个PrintWriter对象呢?
         * 返回响应给客户端 你如果想自己实现一遍response的功能当然也OK
         * response限制在当前http请求中,与request相呼应。
         */
        String jsonStr = gson.toJson(map);  // 自动写入,不必再调用out.write()方法,否则会重复。
        out.println(jsonStr);
        // out用完后需要 flush 一下,清空一下缓冲区
        out.flush();
    }

到现在JSON的使用与简单解析就差不多已经讲完了,这块呢是交互的重点部分,因为涉及到数据的交互,如果前后端连数据都交互不正确的话,那这这这就没法交互成功了,所以前端要搞懂ajax,后端也需要稍有了解,对于JSON则是都要比较清楚明白。

本次JSON暂时不布置作业了,前后端队友可以花点时间交流一下对于ajax以及JSON的理解。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值