前言: 最近也是期末了,有好多好多文档和实验报告要交,所以都没啥时间写文,这段时间清闲了,来补一下之前学习时遗漏的一些知识树,话说就没人吐槽这个JSON图标好丑吗?

什么是JSON

  • JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
  • JSON 是轻量级的文本数据交换格式
  • JSON 独立于语言 *
  • JSON 具有自我描述性,更易理解

JSON 使用 JavaScript 语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。

这里有意思的是,JSON本来是用来表示 JavaScript 对象的一种数据文本格式,但由于它轻量级、易于解析/操作(JavaScript原生支持)的一些特点,渐渐的被很多语言支持也就成了一种标准


为什么使用JSON

在JSON之前,我们通常在网络传输中使用的格式是XML,在我们的印象之中,XML具有很好的可读性,并且格式统一,解析起来也相对比较简单,为什么摒弃掉XML而逐渐的使用起JSON呢?

主要原因在于:JSON比XML更小、更快、更易解析。

  • JavaScript原生支持JSON,解析速度相较XML会更快;
  • XML解析成DOM对象的时候,浏览器之间会产生差异【例如IE和FireFox】;
  • JSON有很多强大的库能够帮助我们更快更简单的完成工作

XML与JSON实例比较

接下来我们通过一个实例的比较来真实的说明一下XML与JSON的区别:

  1. 使用XML表示中国部分省市的数据如下:
<?xml version="1.0" encoding="utf-8" ?>
<country>
<name>中国</name>
<province>
<name>黑龙江</name>
<citys>
<city>哈尔滨</city>
<city>大庆</city>
</citys>   
</province>
<province>
<name>广东</name>
<citys>
<city>广州</city>
<city>深圳</city>
<city>珠海</city>
</citys>   
</province>
<province>
<name>台湾</name>
<citys>
<city>台北</city>
<city>高雄</city>
</citys> 
</province>
<province>
<name>新疆</name>
<citys>
<city>乌鲁木齐</city>
</citys>
</province>
</country>
  1. 使用JSON中国部分省市数据如下:
var country =
{
name: "中国",
provinces: [
{ name: "黑龙江", citys: { city: ["哈尔滨", "大庆"]} },
{ name: "广东", citys: { city: ["广州", "深圳", "珠海"]} },
{ name: "台湾", citys: { city: ["台北", "高雄"]} },
{ name: "新疆", citys: { city: ["乌鲁木齐"]} }
]
}
  • 从编码的可读性来说XML有明显的优势,毕竟人类的语言更贴近这样的说明结构。而JSON读起来更像是一个数据块,读起来比较费解,不过我们读起来费解的语言,恰恰是适合机器于都的,所以通过JSON是的索引contry.provinces[0].name就可以读取到“黑龙江”这个值

  • 从编码的手写难度来说XML还是更简单一些,好读也就意味着好写;不过JSON写出来的字符明显就少很多;去掉空白制表以及换行的话,JSON就是密密麻麻的有用数据,而XML却包含很多重复的标记字符。

JSON相比XML的不同之处

  • 没有结束标签
  • 更短
  • 读写的速度更快
  • 能够使用内建的 JavaScript eval() 方法进行解析
  • 使用数组
  • 不使用保留字
对于AJAX应用程序员来说,JSON比XML更快更易使用:

使用XML:

  • 读取XML文档
  • 使用XML DOM来循环遍历文档
  • 读取值并存储在变量中

使用JSON:

  • 读取JSON字符串
  • 用 eval() 处理JSON字符串

JSON语法

客户端与服务器交换的数据无非就是两种: 数组或者是对象,JSON所表示的数据也就是这两种了

JSON语法是JavaScript语法的子集,在JavaScript中用[]中括号来表示数组,用{}大括号来表示对象,JSON也是这样

JSON数组:

[]中括号里面的内容有些像ArrayList,是一个列表一样的东西

var employees = [
{ "firstName":"Bill" , "lastName":"Gates" },
{ "firstName":"George" , "lastName":"Bush" },
{ "firstName":"Thomas" , "lastName": "Carter" }
];

JSON对象:

{}大括号里面的东西有些像Map,是一对一对的键值对

var obj = {

    age:20,
str:"wmyskxz",
method:function() {
alert("我爱学习");
} };
  • 注意:[]中括号和{}大括号之间是可以相互嵌套的

解析JSON

在解析JSON对象之前,我们需要首先地来创造一个JSON对象:

<script>
var JASONObject = {"name": "我没有三颗心脏", "age": 21};
</script>

使用HTML解析

在HTML中我们可以直接使用.点号来直接访问JSON对象的属性:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JSON学习</title>
</head>
<body>
<p>
Name:<span id="name"></span><br>
Age:<span id="age"></span><br>
</p> <script>
var JASONObject = {"name": "我没有三颗心脏", "age": 21}; document.getElementById("name").innerHTML = JASONObject.name;
document.getElementById("age").innerHTML = JASONObject.age;
</script>
</body>
</html>

打开网页我们能正确看到如下效果:

但通常情况中,我们拿到和上传的并不是一个真正的JSON对象,而是一串由JSON转换得来的字符串,我们同样在HTML中模拟解析一下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JSON学习</title>
</head>
<body>
<p>
Name:<span id="name"></span><br>
Age:<span id="age"></span><br>
</p> <script>
var txt = '{"students":[' +
'{"name":"我没有三颗心脏0","age":21},' +
'{"name":"我没有三颗心脏1","age":21 }]}'; var obj = eval("(" + txt + ")"); document.getElementById("name").innerHTML = obj.students[1].name;
document.getElementById("age").innerHTML = obj.students[1].age;
</script>
</body>
</html>

打开网页即可看到如下正确效果:

从前端发送JSON数据到后台

我们这里演示使用AJAX请求的方式来提交JSON数据到后台:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JSON学习</title>
<!-- 因为不想手动引感觉挺麻烦,引了个菜鸟教程的 -->
<script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
<form>
id:<input type="text" id="id" value="123"/><br/>
名称:<input type="text" id="name" value="category xxx"/><br/>
<input type="button" value="提交" id="sender">
</form>
<div id="messageDiv"></div> <script>
$('#sender').click(function () {
var id = document.getElementById('id').value;
var name = document.getElementById('name').value;
var category = {"name": name, "id": id};
var jsonData = JSON.stringify(category);
var page = "category"; $.ajax({
type: "put",
url: page,
data: jsonData,
dataType: "json",
contentType: "application/json;charset=UTF-8",
success: function (result) {
}
});
alert("提交成功,请在springboot控制台查看服务端接收到的数据"); });
</script>
</body>
</html>
  • 注意: 在上面的例子中,我们使用了 JSON.stringify() 来将一个JSON对象转换成了一串字符串,并且在AJAX中,我们设置了 dataTypecontentType 来告知后台我们传输的是一个JSON数据

简单写一个Controller来验证一下吧:

@PutMapping("/category")
public void addCategory(@RequestBody Category category) throws Exception {
System.out.println("springboot接受到浏览器以JSON格式提交的数据:" + category.getId() + category.getName());
} -----------控制台打印信息:----------
springboot接受到浏览器以JSON格式提交的数据:123 category xxx
  • @RequestBody 注解后面讲到,这里只做简单演示

JSON库介绍

引用自:几种常用JSON库性能比较

在后台有许多支持解析JSON的库,目前对于Java开源的JSON类库有许多,下面我们介绍三种比较常用的JSON库,并进行比对说明,它们分别是:

  • Gson(项目地址:https://github.com/google/gson)

    • Gson是目前功能最全的Json解析神器,Gson当初是为因应Google公司内部需求而由Google自行研发而来,但自从在2008年五月公开发布第一版后已被许多公司或用户应用。Gson的应用主要为toJson与fromJson两个转换函数,无依赖,不需要例外额外的jar,能够直接跑在JDK上。而在使用这种对象转换之前需先创建好对象的类型以及其成员才能成功的将JSON字符串成功转换成相对应的对象。类里面只要有get和set方法,Gson完全可以将复杂类型的json到bean或bean到json的转换,是JSON解析的神器。
  • FastJson(项目地址:https://github.com/alibaba/fastjson)

    • Fastjson是一个Java语言编写的高性能的JSON处理器,由阿里巴巴公司开发。无依赖,不需要例外额外的jar,能够直接跑在JDK上。FastJson在复杂类型的Bean转换Json上会出现一些问题,可能会出现引用的类型,导致Json转换出错,需要制定引用。FastJson采用独创的算法,将parse的速度提升到极致,超过所有json库。
  • Jackson(项目地址:https://github.com/FasterXML/jackson)

    • 相比json-lib框架,Jackson所依赖的jar包较少,简单易用并且性能也要相对高些。而且Jackson社区相对比较活跃,更新速度也比较快。Jackson对于复杂类型的json转换bean会出现问题,一些集合Map,List的转换出现问题。Jackson对于复杂类型的bean转换Json,转换的json格式不是标准的Json格式。

到底使用哪一个JSON库呢?

我看了一些资料,比较印象深刻的是:FastJson在复杂类型的Bean转换Json上会出现一些问题,但是在解析JSON时却是最快的(具体参考:知乎:fastjson这么快老外为啥还是热衷 jackson?

总结如下:

  • FastJson的API设计的最简单,最方便使用,直接使用JSON的两个静态方法即可完成四种操作;而Gson和Jackson都需要new一个对象;
  • 数据量大时,使用Jackson;
  • 如果有性能要求可以使用Gson/Jackson将bean转换json确保数据的正确性,使用FastJson将Json转换成Bean

三种JSON库简要使用说明

为了导库简单,我在这里都使用Maven搭建的SpringBoot项目来演示,Maven库的地址在这里:https://mvnrepository.com/

在使用之前,我们先来建设一些基础类,用于支持JSON库的使用:

public class Person {

	private String name;
private Integer age; /* getter and setter */ @Override
public String toString() {
return "名字为" + name + ",年龄" + age;
}
}

Gson库使用简要说明

(1)Maven依赖:

<!-- Gson库 -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>

(2)使用示例:

@Test
public void tester() {
Gson gson = new Gson(); /* —————————————————— 准备测试数据 —————————————————— */ Person person1 = new Person();
person1.setName("我没有三颗心脏1");
person1.setAge(21); Person person2 = new Person();
person2.setName("我没有三颗心脏2");
person2.setAge(21); Person person3 = new Person();
person3.setName("我没有三颗心脏3");
person3.setAge(21); List<Person> list = new ArrayList<>();
list.add(person1);
list.add(person2);
list.add(person3); /* —————————————————— 简单的Bean转为JSON —————————————————— */
String jsonString = gson.toJson(person1);
System.out.println("简单的Bean转为JSON:" + jsonString); /* —————————————————— JSON转为简单Bean —————————————————— */
Person personFromJson = gson.fromJson(jsonString, Person.class);
System.out.println("JSON转为简单Bean:" + personFromJson.toString()); /* —————————————————— 带泛型的List转JSON —————————————————— */
String jsonStringFromList = gson.toJson(list);
System.out.println("带泛型的List转JSON:" + jsonStringFromList); /* —————————————————— JSONz转为带泛型的List —————————————————— */
List<Person> retList = gson.fromJson(jsonStringFromList, new TypeToken<List<Person>>() {
}.getType());
for (Person tempPerson : retList) {
System.out.println(tempPerson.toString());
} } ------------------结果如下------------------
简单的Bean转为JSON:{"name":"我没有三颗心脏1","age":21}
JSON转为简单Bean:名字为我没有三颗心脏1,年龄21
带泛型的List转JSON:[{"name":"我没有三颗心脏1","age":21},{"name":"我没有三颗心脏2","age":21},{"name":"我没有三颗心脏3","age":21}]
名字为我没有三颗心脏1,年龄21
名字为我没有三颗心脏2,年龄21
名字为我没有三颗心脏3,年龄21

好文推荐及扩展阅读:你真的会用Gson吗?Gson使用指南(一)


FastJson库简要使用说明

(1)Maven依赖:

<!-- FastJson库 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>

(2)使用示例:

@Test
public void tester() { /* —————————————————— 准备测试数据 —————————————————— */ Person person1 = new Person();
person1.setName("我没有三颗心脏1");
person1.setAge(21); Person person2 = new Person();
person2.setName("我没有三颗心脏2");
person2.setAge(21); Person person3 = new Person();
person3.setName("我没有三颗心脏3");
person3.setAge(21); List<Person> list = new ArrayList<>();
list.add(person1);
list.add(person2);
list.add(person3); /* —————————————————— 简单的Bean转为JSON —————————————————— */
String jsonString = JSON.toJSONString(person1);
System.out.println("简单的Bean转为JSON:" + jsonString); /* —————————————————— JSON转为简单Bean —————————————————— */
Person personFromJson = JSON.parseObject(jsonString, Person.class);
System.out.println("JSON转为简单Bean:" + personFromJson.toString()); /* —————————————————— 带泛型的List转JSON —————————————————— */
String jsonStringFromList = JSON.toJSONString(list);
System.out.println("带泛型的List转JSON:" + jsonStringFromList); /* —————————————————— JSONz转为带泛型的List —————————————————— */
List<Person> retList = JSON.parseObject(jsonStringFromList, new TypeReference<List<Person>>() {
});
for (Person tempPerson : retList) {
System.out.println(tempPerson.toString());
} } ------------------结果如下------------------
简单的Bean转为JSON:{"age":21,"name":"我没有三颗心脏1"}
JSON转为简单Bean:名字为我没有三颗心脏1,年龄21
带泛型的List转JSON:[{"age":21,"name":"我没有三颗心脏1"},{"age":21,"name":"我没有三颗心脏2"},{"age":21,"name":"我没有三颗心脏3"}]
名字为我没有三颗心脏1,年龄21
名字为我没有三颗心脏2,年龄21
名字为我没有三颗心脏3,年龄21

官方文档:戳这里,据官方说法,FastJson比Gson要快上6倍哦!


Jackson库使用简要说明

(1)Maven依赖:

稍微麻烦一点的是Jackson需要依赖三个包

<!-- jackson库 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.5</version>
</dependency>

(2)使用示例:

@Test
public void tester() throws IOException { /* —————————————————— 准备测试数据 —————————————————— */ Person person1 = new Person();
person1.setName("我没有三颗心脏1");
person1.setAge(21); Person person2 = new Person();
person2.setName("我没有三颗心脏2");
person2.setAge(21); Person person3 = new Person();
person3.setName("我没有三颗心脏3");
person3.setAge(21); List<Person> list = new ArrayList<>();
list.add(person1);
list.add(person2);
list.add(person3); /* ObjectMapper是JSON操作的核心,Jackson的所有JSON操作都是在ObjectMapper中实现的 */
ObjectMapper mapper = new ObjectMapper(); /* —————————————————— 简单的Bean转为JSON —————————————————— */
String jsonString = mapper.writeValueAsString(person1);
System.out.println("简单的Bean转为JSON:" + jsonString); /* —————————————————— JSON转为简单Bean —————————————————— */
Person personFromJson = mapper.readValue(jsonString, Person.class);
System.out.println("JSON转为简单Bean:" + personFromJson.toString()); /* —————————————————— 带泛型的List转JSON —————————————————— */
String jsonStringFromList = mapper.writeValueAsString(list);
System.out.println("带泛型的List转JSON:" + jsonStringFromList); /* —————————————————— JSONz转为带泛型的List —————————————————— */
// List<LinkedHashMap<String, Person>> retList = mapper.readValue(jsonStringFromList, List.class);
// for (int i = 0; i < retList.size(); i++) {
// Map<String, Person> map = retList.get(i);
// Set<String> set = map.keySet();
// for (Iterator<String> it = set.iterator(); it.hasNext();) {
// String key = it.next();
// System.out.println(key + ":" + map.get(key));
// }
// }
/* —————————————————— JSONz转为Array数组 —————————————————— */
Person[] retList = mapper.readValue(jsonStringFromList, Person[].class);
for (int i = 0; i < retList.length; i++) {
System.out.println(retList[i].toString());
} } ------------------结果如下------------------
简单的Bean转为JSON:{"name":"我没有三颗心脏1","age":21}
JSON转为简单Bean:名字为我没有三颗心脏1,年龄21
带泛型的List转JSON:[{"name":"我没有三颗心脏1","age":21},{"name":"我没有三颗心脏2","age":21},{"name":"我没有三颗心脏3","age":21}]
名字为我没有三颗心脏1,年龄21
名字为我没有三颗心脏2,年龄21
名字为我没有三颗心脏3,年龄21
  • 几点注意:

    1.由于Jackson底层代码抛出了IOEception,所以我们在调用的时候也需要抛出;

    2.Jackson所有的操作都是基于ObjectMapper

在框架中使用JSON

SpingMVC和SpringBoot一样,都能通过注解的方式获取并返回一串JSON格式的数据,我们使用SpringBoot的一段实例程序来实际说明一下:

@RequestMapping("/jsonCategory")
@ResponseBody // 该注解表示我们的请求不再交给springmvc处理,而是结合JSON包,将对象解析成JSON字符串
public Category jsonCategory() {
return new Category(123, "我没有三颗心脏");
}

我们在浏览器中访问地址:localhost:8080/jsonCategory,会得到以下JSON数据:

我们也可以使用 @RequestBody 来获取一串JSON数据:

@PutMapping("/category")
public void addCategory(@RequestBody Category category) {
System.out.println("springboot接受到浏览器以JSON格式提交的数据:" + category.getId() + category.getName());
}

我们在前台使用的是上面用过的用于提交JSON数据的页面,运行能够成功得到结果:

  • 注意: Spring4 之后新加入了 @RestController 注解,是@ResponseBody和@Controller的组合注解,用于返回JSON数据。

欢迎转载,转载请注明出处!

简书ID:@我没有三颗心脏

github:wmyskxz

欢迎关注公众微信号:wmyskxz_javaweb

分享自己的Java Web学习之路以及各种Java学习资料

JavaWeb中使用JSON的更多相关文章

  1. 开发过程中关于JSON的那些事

    在使用过程中,对JSON了解的还不够,特地整理一下,用于个人学习和知识参考. 1.IBM的json入门指南    json官网 2.javaweb中发送接收解析问题 3.Java解析json,以及js ...

  2. 如何正确的使用json?如何在.Net中使用json?

    什么是json json是一种轻量级的数据交换格式,由N组键值对组成的字符串,完全独立于语言的文本格式. 为什么要使用json 在很久很久以前,调用第三方API时,我们通常是采用xml进行数据交互,但 ...

  3. C#中的Json的序列化和反序列化

    Json是一种通用的数据格式,我们在数据交换的时候,经常会用到,下面介绍c#中的json序列化和反序列化,当然也可用在asp.net,silverlight,wpf中.我们在下面实例讲解如何进行Jso ...

  4. SpringMVC中使用Json传数据

    在web项目中使用Json进行数据的传输是非常常见且有用的,在这里介绍下在SpringMVC中使用Json传数据的一种方法,在我的使用中,主要包括下面四个部分(我个人喜好使用maven这类型工具进行项 ...

  5. PHP中生成json信息的方法

    <?php //php中生成json信息 //json_encode(数组/对象) $color = array('red','blue','green'); //[索引数组] echo jso ...

  6. 【ASP.NET Web API教程】6.2 ASP.NET Web API中的JSON和XML序列化

    谨以此文感谢关注此系列文章的园友!前段时间本以为此系列文章已没多少人关注,而不打算继续下去了.因为文章贴出来之后,看的人似乎不多,也很少有人对这些文章发表评论,而且几乎无人给予“推荐”.但前几天有人询 ...

  7. Asp.Net Web API 2第十三课——ASP.NET Web API中的JSON和XML序列化

    前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文描述ASP.NET W ...

  8. JMeter中返回Json数据的处理方法

    Json 作为一种数据交换格式在网络开发,特别是 Ajax 与 Restful 架构中应用的越来越广泛.而 Apache 的 JMeter 也是较受欢迎的压力测试工具之一,但是它本身没有提供对于 Js ...

  9. 在JavaWeb中使用Log4j步骤

    在JavaWeb中使用Log4J指南.每次在开始写一个项目的时候都忘记Log4J如何配置.所以写个步骤,作为记录. 第一步 下载Log4J jar包 从Apache Logging Services ...

随机推荐

  1. CentOS Linux搭建SVN服务器

    Linux系统:CentOS 安装步骤如下: 1.yum install subversion 2.输入rpm -ql subversion查看安装位置,如下图: 可以看到 svn在bin目录下生成了 ...

  2. Python爬虫开发与项目实战

    Python爬虫开发与项目实战(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1MFexF6S4No_FtC5U2GCKqQ 提取码:gtz1 复制这段内容后打开百度 ...

  3. linux仅修改文件夹权限 分别批量修改文件和文件夹权限

    比如我想把/var/www/html下的文件全部改成664,文件夹改成775,怎么做呢 方法一: 先把所有文件及文件夹改成664,然后把所有文件夹改成775 chmod -R 664 ./ find ...

  4. Do-Now—团队 冲刺博客六

    Do-Now-团队 冲刺博客六 作者:仇夏 前言 终于从四级的考试中解脱了(不过我觉得可能凉凉,呵呵),我们的APP制作也迎来了最后的两天. 自己觉得自己其实没有干成什么事情,代码什么的大都是队友们写 ...

  5. C++进阶:新人易入的那些坑 --1.常量、常指针和指针常量

    声明:以下内容B站/Youtube学习笔记,https://www.youtube.com/user/BoQianTheProgrammer/ Advanced C++. /* why use con ...

  6. c#提交事务的两种方法

    1. using (TransactionScope ts = new TransactionScope()) { 除非显示调用ts.Complete()方法.否则,系统不会自动提交这个事务.如果在代 ...

  7. js深度复制三种方法

    1.用递归的方式进行深度复制 2.用JSON.stringify加上JSON.parse()进行深度复制 3.用jquery中自带的方法$.extend()进行深度复制 具体实现代码可百度自行查询

  8. Mesos源码分析(15): Test Executor的运行

    Test Executor的代码在src/examples/test_executor.cpp中   int main(int argc, char** argv) {   TestExecutor ...

  9. DCOS实践分享(3):基于Mesos 和 Docker 企业级移动应用实践分享

    2016年1月24日 8:00—19:00 北京万豪酒店(东城区建国门南大街7号) @Container大会是由国内容器社区DockOne组织的专为一线开发者和运维工程师设计的顶级容器技术会议,会议强 ...

  10. Azure Web连接到Azure MySql Db

    这个问题折腾了好一会,简单记录一下. 两种方式: 输入"规则名称"."起始 IP"和"结束 IP",然后单击"保存". ...