JSON教程(非常详细)
参考文章来源:JSON教程(非常详细)
目录
JSON
JSON 全称“JavaScript Object Notation”,译为“JavaScript 对象简谱”或“JavaScript 对象表示法”,是一种轻量级的、基于文本的、开放的数据交换(数据交换是指,两个设备之间建立连接并互相传递数据的过程)格式。是一种纯字符串形式的数据,它本身不提供任何方法(函数),非常适合在网络中进行传输。
JSON 发展史
2000 年初,Douglas Crockford(道格拉斯·克罗克福特)发明了 JSON,并从 2001 年开始推广使用。同年 4 月,位于旧金山湾区某车库的一台计算机发出了首个 JSON 格式的数据,这是计算机历史上的重要时刻。
图:道格拉斯·克罗克福特
2005-2006 年,JSON 正式成为主流的数据格式,雅虎、谷歌等知名网站开始广泛使用 JSON 格式。
2013 年,ECMA International(欧洲计算机制造商协会)制定了 JSON 的语法标准——ECMA-404。
经过 20 年左右的发展,JSON 已经替代了 XML,成为了 Web 开发中首选的数据交换格式。
为什么要使用 JSON?
JSON和XML都能够实现在互联网中数据传输。之所以使用 JSON,最主要的原因是 JavaScript。众所周知,JavaScript 是 Web 开发中不可或缺的技术之一,而 JSON 是基于 JavaScript 的一个子集,JavaScript 默认就支持 JSON,而且只要您学会了 JavaScript,就可以轻松地使用 JSON,不需要学习额外的知识。
- 结构简单、紧凑:与 XML 相比,JSON 遵循简单、紧凑的风格,有利于程序员编辑和阅读,而 XML 相对比较复杂;
- 更快:JSON 的解析速度比 XML 更快(因为 XML 与 HTML 很像,在解析大型 XML 文件时需要消耗额外的内存),存储同样的数据,JSON 格式所占的存储空间更小;
- 可读性高:JSON 的结构有利于程序员阅读。
JSON 的不足
- 只有一种数字类型:JSON 中只支持 IEEE-754 双精度浮点格式,因此您无法使用 JSON 来存储许多编程语言中多样化的数字类型;
- 没有日期类型:在 JSON 中您只能通过日期的字符串(例如:1970-01-01)或者时间戳(例如:1632366361)来表示日期;
- 没有注释:在 JSON 中无法添加注释;
- 冗长:虽然 JSON 比 XML 更加简洁,但它并不是最简洁的数据交换格式,对于数据量庞大或用途特殊的服务,您需要使用更加高效的数据格式。
存储格式
JSON 数据可以存储在 .json 格式的文件中(与 .txt 格式类似,都属于纯文本文件),也可以将 JSON 数据以字符串的形式存储在数据库、Cookie、Session 中。
使用场景
1) 定义接口
- 使用 Ajax 异步加载的数据;
- RPC 远程调用;
- 前后端分离,后端返回的数据;
- 开发 API,例如百度、高德的一些开放接口。
2) 序列化
程序在运行时所有的变量都是存储在内存中的,将这些数据保存到数据库中,也可以保存到一个文件中,这个将内存中数据保存起来的过程称为序列化。序列化在 Python 中称为 pickling,在其他语言中也被称为 serialization、marshalling、flattening 等等,都是一个意思。
通常情况下,序列化是将程序中的对象直接转换为可保存或者可传输的数据,但这样会保存对象的类型信息,无法做到跨语言使用,例如我们使用 Python 将数据序列化到硬盘,然后使用 Java 来读取这份数据,这时由于不同编程语言的数据类型不同,就会造成读取失败。如果在序列化之前,先将对象信息转换为 JSON 格式,则不会出现此类问题。
3) 生成 Token
JSON 格式的 Token 最有代表性的是 JWT(JSON Web Tokens)
JSON Web Token Introduction - jwt.io
4) 配置文件
npm(Node.js 的包管理工具)的 package.json
{
"name": "server",
"version": "0.0.0",
"private": true,
"main": "server.js",
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"cookie-parser": "~1.4.3",
"debug": "~2.6.9",
"express": "~4.16.0",
"http-errors": "~1.6.2",
"jade": "~1.11.0",
"morgan": "~1.9.0"
}
}
JSON语法规则
- Object(对象):键/值对(名称/值)的集合,使用花括号
{ }
定义。在每个键/值对中,以键开头,后跟一个冒号:
,最后是值。多个键/值对之间使用逗号,
分隔,例如{"name":"C语言中文网","url":"http://c.biancheng.net"}
; - Array(数组):值的有序集合,使用方括号
[ ]
定义,数组中每个值之间使用逗号,
进行分隔。 - 键:JSON 数据是以键/值对(名称/值)的形式书写的,键表示数据的名称,需要以字符串的形式定义(在双引号中定义),后面紧跟一个冒号,最后是值,如下例所示:
"name":"C语言中文网"
- 值:支持很多数据类型。
- 数字(整数或浮点数);
- 字符串(需要在双引号中定义);
- 布尔值(true 或 false);
- 数组(在方括号中定义);
- 对象(在花括号中定义);
- null(空)。
JSON 与 JavaScript 对象的区别
JSON 是一种数据交换格式,可以跨语言、跨平台使用,它只是与 JavaScript 有些渊源,并不是 JavaScript 的一部分。
在 JavaScript 对象中,您既可以使用双引号也可以使用单引号,但在 JSON 中只能使用双引号。还有就是 JSON 中没有日期类型,也不能定义注释,所以您只能通过日期的字符串(例如:1970-01-01)或者时间戳(例如:1632366361)来表示日期。
语法:
// JavaScript 中的对象
{
foo: "bar"
}
// JSON
{
"foo": "bar"
}
JSON数据类型
1、字符串
字符串中也可以包含一些转义字符
\\
反斜线本身;\/
正斜线;\"
双引号\b
退格;\f
换页;\n
换行;\r
回车;\t
水平制表符;\u
四位的十六进制数字。
2、数字
JSON 中不区分整型和浮点型,只支持使用 IEEE-754 双精度浮点格式来定义数字。此外,JSON 中不能使用八进制和十六进制表示数字,但可以使用 e 或 E 来表示 10 的指数。
{
"number_1" : 210,
"number_2" : -210,
"number_3" : 21.05,
"number_4" : 1.0E+2
}
3、布尔值
{
"message" : true,
"pay_succeed" : false
}
4、空
{
"id" : 1,
"visibility" : true,
"popularity" : null
}
5、对象
{
"author": {
"name": "一百减一是零",
"url": "https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343"
}
}
6、数组
{
"course" : [
"JSON 教程",
"JavaScript 教程",
"HTML 教程",
{
"website" : "一百减一是零",
"url" : "https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343"
},
[
3.14,
true
],
null
]
}
JSON注释
想要在 JSON 中添加注释,我们可以在要添加注释键/值对的前面(或后面)添加一个同名的键,并在键名中添加一个特殊字符加以区分,例如@
、#
、?
、_
、/
等,然后在与键对应的值中定义注释的内容。
{
"@name": "网站名称",
"name": "一百减一是零",
"_url": "网址",
"url": "https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343",
"course": "JSON 教程",
"@charge": "0=收费; 1=免费",
"charge": 1,
"#list": "教程目录",
"list": [
"JSON数据类型",
"JSON对象",
"JSON数组"
],
"message": {
"code": 0,
"message": "OK",
"#data": {
"#id": "用户ID",
"#type": "0=正常; 1=异常",
"#name": "姓名",
"#createTime": "创建时间(yyyy-MM-dd)"
},
"data": {
"id": "12345",
"type": 0,
"name": "我的名字",
"createTime": "2020-05-20"
}
}
}
除了可以在键名中添加特殊字符外,也可以直接以“comment”、“_comment” 或 “__comment”作为键名来定义注释,如下例所示:
{
"_comment": "(https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343/)—— 一个在线学习编程的网站",
"course": {
"name": "JSON 教程",
"url": "https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343"
}
}
JSON5
与 JSON 相比,JSON5 做出了如下改变:
- 在对象或数组的末尾(即最后一个键/值对或值),可以添加逗号;
- 字符串可以使用单引号定义;
- 字符串中可以包含转义字符,并且可以跨越多行;
- 可以定义十六进制的数字;
- 数字可以包含前导或后导的小数点;
- 数字前可以添加一个加、减号来表示正负数;
- 可以使用
//
来定义单行注释,使用/* ... */
来定义多行注释。
{
// 网站名称
"name": "一百减一是零",
// 网址
"url": "https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343",
"course": "JSON 教程",
// 0=收费; 1=免费
"charge": 1,
// 教程目录
"list": [
"JSON数据类型",
"JSON对象",
"JSON数组"
],
"message": {
"code": 0,
"message": "OK",
/*
id = 用户ID
type = 0=正常; 1=异常
name = 姓名
createTime = 创建时间(yyyy-MM-dd)
*/
"data": {
"id": "12345",
"type": 0,
"name": "我的名字",
"createTime": "2020-05-20"
}
}
}
前端使用
引入<script src="https://unpkg.com/json5@^2.0.0/dist/index.min.js"></script>
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript</title>
</head>
<body>
<script src="https://unpkg.com/json5@^2.0.0/dist/index.min.js"></script>
<script>
var arr = {
// 网站名称
"name": "一百减一是零",
// 网址
"url": "https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343",
"course": "JSON 教程",
// 0=收费; 1=免费
"charge": 1,
// 教程目录
"list": [
"JSON数据类型",
"JSON对象",
"JSON数组"
],
"message": {
"code": 0,
"message": "OK",
/*
id = 用户ID
type = 0=正常; 1=异常
name = 姓名
createTime = 创建时间(yyyy-MM-dd)
*/
"data": {
"id": "12345",
"type": 0,
"name": "我的名字",
"createTime": "2020-05-20"
}
}
};
var str = JSON5.stringify(arr);
console.log(arr)
</script>
</body>
</html>
运行结果
JSON Schema
在 JSON Schema 中可以规定要在 JSON 中出现的字段、字段含义、字段类型等信息,而且可以使用 JSON Schema 来校验 JSON 数据是否符合 Schema 中定义的规范。
定义 Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"name": { "type": "string" },
"email": { "type": "string" },
"age": {
"type": "number",
"minimum": 0,
"exclusiveMinimum": false
},
"telephone": {
"type": "string",
"pattern": "^(\\([0-9]{3}\\))?[0-9]{3}-[0-9]{4}$"
}
},
"required": ["name", "email"],
"additionalProperties": false
}
上面 Schema 中,要求 JSON 数据必须符合以下要求
- 类型为 object;
- JSON 中可以包含以下四个键:
- name:必须是字符串类型;
- email:必须是字符串类型;
- age:必须是大于 0 的整数;
- telephone:必须是字符串类型,并且需要匹配指定的正则表达式。
- 上面的四个键中,name 和 email 必须定义,而 age 和 telephone 则是可选的;
- 除了上面四个键,不允许出现其它的键。
Schema 中提供了一系列关键字
1) 字符串(String)
关键字 | 描述 | 可选值 |
---|---|---|
minLength | 字符串最小长度,不能为负数 | |
maxLength | 字符串最大长度,不能为负数 | |
pattern | 正则表达式 | |
format | 字符串格式 | "date-time":日期和时间,如 2018-11-13T20:20:39+00:00 "time":时间,如 20:20:39+00:00 "date":日期,如 2018-11-13 "email":电子邮箱地址 "hostname":主机名 "ipv4":IPv4 地址 "ipv6":IPv6 地址 "uri":通用资源标识符(URI) "uri-template":URI 模板(任何级别) "regex":正则表达式 |
2) 数值类型
关键字 | 描述 | 示例 |
---|---|---|
integer | 整数 | {"type": "integer"} |
number | 数字,包括整数和浮点数 | {"type": "number"} |
multipleOf | 数字必须是给定数字(正数)的倍数 | {"type": "number", "multipleOf": 3} |
minimum | 数值允许的最小值 | {"type": "number", "minimum": 1} |
maximum | 数值允许的最大值 | {"type": "number", "maximum": 9} |
3) 对象
属性(Properties)
{
"type": "object",
"properties": {
"name": { "type": "string"},
"age": {"type": "number", "multipleOf": 3},
"date": {
"type": "string",
"format": "date"
}
}
}
额外属性(Asdditional Properties)
{
"type": "object",
"properties": {
"number": { "type": "number"},
"street_name": { "type": "string"},
"street_type": {
"type": "string",
"enum": ["Street", "Avenue", "Boulevard"]
}
},
"additionalProperties": { "type": "string"}
}
必须属性(Required Properties)
{
"type": "object",
"properties": {
"name": { "type": "string" },
"email": { "type": "string" },
"address": { "type": "string" },
"telephone": { "type": "string" }
},
"required": ["name", "email"]
}
属性名称(Property names)
propertyNames 定义 JSON 数据中键的命名规则
{
"type": "object",
"propertyNames": {
"pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
}
}
属性个数(Size)
{
"type": "object",
"minProperties": 2,
"maxProperties": 3
}
4) 数组
列表验证(List validation)
任意长度的数组,数组中每个值都匹配相同的 Schema;
验证数组的所有值为数字
{
"type": "array",
"items": {
"type": "number"
}
}
contains 关键字仅需要针对数组中的一个或多个项目进行验证,如下例所示(只需包含至少一个数字元素):
{
"type": "array",
"contains": {
"type": "number"
}
}
元组验证(Tuple validation)
固定长度的数组,数组中每个值可以匹配不同的 Schema。
值的类型也可能是不同的,例如:
[编号, 街道名称, 街道类型, 方向]
{
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "string"
},
{
"type": "string",
"enum": ["Street", "Avenue", "Boulevard"]
},
{
"type": "string",
"enum": ["NW", "NE", "SW", "SE"]
}
]
}
数组长度(Length)
{
"type": "array",
"minItems": 2,
"maxItems": 3
}
唯一(Uniqueness)
将 uniqueItems 关键字设置为 true 可以确保数组中的每个元素都是唯一的
{
"type": "array",
"uniqueItems": true
}
5) 布尔(boolean)
{"type": "boolean"}
6) 空值(null)
{"type": "null"}
7) 通用关键字
- title 和 description 关键字必须是字符串,“title”最好比较简短,而“description”应该提供关于该 schema 的详细描述;
- default 关键字用来定义默认值;
- examples 关键字是用于提供一系列针对该模式进行验证的示例。
{
"title": "Match anything",
"description": "This is a schema that matches anything.",
"default": "Default value",
"examples": ["Anything", 4035]
}
注释(Comments)
$comment 关键字用于添加注释/批注,它的值必须是一个字符串。
枚举值(Enumerated values)
enum 关键字被用于定义枚举值(一组固定的值),它必须是一个至少包含一个值的数组,而且每个值都必须是唯一的。此外,type 和 enum 是并列的,必须同时满足,如下例所示:
{
"type": "string",
"enum": ["red", "amber", "green"]
}
常量值(Constant values)
const 关键字被用于定义一个常量值
{
"properties": {
"country": {
"const": "United States of America"
}
}
}
const 是 enum 的语法糖,所以下面两个定义是等价的:
{ "const": "United States of America" }
{ "enum": [ "United States of America" ]}
8) $schema 关键字
$schema 关键字用于声明 JSON Schema 的版本,建议所有 JSON Schema 都声明一个 $schema,并且应该是 Schema 的第一个键/值对,如下例所示:
{"$schema": "http://json-schema.org/draft-04/schema#"}
如果需要声明 JSON Schema 的指定版本,则可以将 $schema 的值设置为以下几个:
- http://json-schema.org/draft-07/schema#
- http://json-schema.org/draft-06/schema#
- http://json-schema.org/draft-04/schema#
9) $ref 关键字
$ref 关键字用于引用其他地方的一个 Schema 片段,它的值为一个 URI 引用。如果是引用同一文档的 Schema 片段,则 $ref 的值需要以井号(#)开头,例如:
{ "$ref": "#/definitions/address" }
上面示例中的“#/definitions/address”意味着:
- 转到文档的根;
- 找到 "definitions" 键的值;
- 在该对象中,找到键 "address" 的值。
如果要引用另外的 Schema 文件,可以向下面这样:
{ "$ref": "definitions.json#/address" }
示例
{
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"address": {
"type": "object",
"properties": {
"street_address": { "type": "string" },
"city": { "type": "string" },
"state": { "type": "string" }
},
"required": ["street_address", "city", "state"]
}
},
"type": "object",
"properties": {
"billing_address": { "$ref": "#/definitions/address" },
"shipping_address": { "$ref": "#/definitions/address" }
}
}
使用 $ref 关键字也可以引用当前 Schema 中的某一部分(类似于编程中的递归)。例如您有一个 person 模式,其中包含一个数组 children,每个数组也是一个 person 实例,如下例所示:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"person": {
"type": "object",
"properties": {
"name": { "type": "string" },
"children": {
"type": "array",
"items": { "$ref": "#/definitions/person" },
"default": []
}
}
}
},
"type": "object",
"properties": {
"person": { "$ref": "#/definitions/person" }
}
}
10) $id 关键字
$id 关键字的值是一个 URI 引用,它有两个用途:
- 为 Schema 声明一个唯一的标识符;
- 声明一个基本 URI,$ref 可以基于该 URI 进行引用。
例如我们要引用 http://c.biancheng.net/ 域名的某个 Schema,则可以将 $id 设置为下面这样:
{ "$id": "http://c.biancheng.net/schemas/address.json" }
注意,当定义了上面所示的 $id 之后,若我们要使用 $ref 来引用同域名下的其它 Schema,则可以简写成如下所示的样子
{ "$ref": "person.json" }
JSON和XML的区别
什么是 XML?
XML 全称“Extensive Markup Language”,译为“可扩展标记语言”,是一种源自 SGML 的、基于文本的数据格式(XML 是 SGML 的一个子集)。是一种专门为了存储数据而创建的标记语言,它的编写方式与 HTML 非常相似,能够通过不同的标签来标记不同的内容。XML 旨在传输或保存数据,而不是显示数据,在 XML 中,没有预定义标签,其中使用的所有标签都是自定义的,而且所有的标签都由两个部分组成,分别是开始标签(例如<tagname>)和结束标签(例如</tagname>)。需要注意的是,XML 中的标签是区分大小写的
样例
<?xml version="1.0" encoding="ISO-8859-1"?>
<note>
<title>JSON教程</title>
<author>一百减一是零</author>
<url>https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343</url>
<catalogue>
<li>JSON是什么?</li>
<li>JSONP是什么?</li>
<li>JSON语法规则</li>
</catalogue>
</note>
优点
是它可以跨平台、跨语言进行传输。另外,XML 数据可以保存在格式为 .xml 的文本文件中。
JSON 与 XML 之间的差异
JSON | XML |
---|---|
JSON 是一种数据格式 | XML 是一种标记语言 |
与 XML 相比,JSON 数据更容易阅读 | XML 文档相对来说阅读起来比较困难 |
JSON 数据可以存储在 .json 格式的文本文件中 | XML 数据可以存储在 .xml 格式的文本文件中 |
JSON 中支持字符串、数字、数组、布尔值等类型 | XML 中只有字符串类型 |
JSON 没有显示功能 | XML 提供了显示数据的能力,因为它是一种标记语言 |
JSON 仅支持 UTF-8 编码 | XML 支持各种编码 |
JSON 不支持注释 | XML 支持注释 |
JSON 不支持命名空间 | XML 支持命名空间 |
JSON 读写速度更快,且更容易解析 | 相对于 JSON,XML 数据结构更加复杂,解析速度相对较慢 |
相对于 XML,JSON 的安全性较低 | 相对于 JSON,XML 的安全性更高 |
JSON和BSON的区别
什么是 BSON?
BSON 全称“Binary Serialized Document Format”,译为“二进制序列化文档格式”,是由 10gen(一家公司的名称)开发的一种数据格式,目前主要用于 MongoDB 数据库中,是 MongoDB 的数据存储格式。
BSON 基于 JSON,在 JSON 的基础上进行了升级,支持更多的数据类型。有时也将 BSON 称为“Binary JSON”,即“二进制 JSON”。
注意:BSON 并非只能用于 MongoDB,它也可以在其它编程语言中使用。
与 JSON 相比,BSON 存取的效率更高,而且占用的空间更小。另外,除了支持 JSON 中的数据类型外,BSON 还支持日期(Date)和二进制(BinData)等类型。
JSON 与 BSON 之间的区别
JSON 和 BSON 之间最主要的区别如下表所示:
JSON | BSON |
---|---|
JSON 是 javascript 对象表示法 | BSON 是二进制 JSON |
是一种轻量级的、基于文本的、开放的数据交换格式 | 是一种二进制序列化文档格式 |
JSON 包含一些基本数据类型,如字符串、数字、布尔值、空值 | 除了支持 JSON 中的类型外,BSON 还包含一些额外的数据类型,例如日期(Date)、二进制(BinData)等 |
AnyDB、redis 等数据库将数据存储为 JSON 格式 | MongoDB 中将数据存储为 BSON 格式 |
主要用于传输数据 | 主要用于存储数据 |
没有响应的编码和解码技术 | 有专用的编码和解码技术 |
如果想从 JSON 文件中读取指定信息,需要遍历整个数据 | 在 BSON 中,可以使用索引跳过到指定内容 |
JSON 格式不需要解析,因为它是人类可读的 | BSON 需要解析,因为它是二进制的 |
JSON 是对象和数组的组合,其中对象是键值对的集合,而数组是元素的有序列表 | BSON 是二进制数据,在其中可以存储一些附加信息,例如字符串长度、对象类型等 |
不同语言的解析和创建
PHP
- json_encode():可以将变量转换为 JSON 格式;
- json_decode():可以对 JSON 格式的字符串进行解析。
json_encode()
json_encode(mixed $value, int $options = 0, int $depth = 512): string | false
参数说明如下:
- $value:要转换的变量,变量可以是任意数据类型;
- $options:可选参数,默认值为 0,可选值为以下 PHP 常量:JSON_FORCE_OBJECT、JSON_HEX_QUOT、JSON_HEX_TAG、JSON_HEX_AMP、JSON_HEX_APOS、JSON_INVALID_UTF8_IGNORE、JSON_INVALID_UTF8_SUBSTITUTE、 JSON_NUMERIC_CHECK、JSON_PARTIAL_OUTPUT_ON_ERROR、JSON_PRESERVE_ZERO_FRACTION、JSON_PRETTY_PRINT、JSON_UNESCAPED_LINE_TERMINATORS、JSON_UNESCAPED_SLASHES、JSON_UNESCAPED_UNICODE、JSON_THROW_ON_ERROR。关于这些常量了解即可,一般不怎么使用,它们的具体含义您可以通过 JSON 常量查阅;
- $depth:可选参数,用来设置递归的最大深度,它的值必须大于 0,默认值为 512,同 $options 参数一样,该参数同样不怎么使用。
若转换成功,json_encode() 函数会返回字符串类型的转换结果,若转换失败,则返回 false。
示例
<?php
$arr = [
"title" => "JSON教程",
"author" => "一百减一是零",
"url" => "https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343",
"catalogue" => [
"JSON是什么?",
"JSONP是什么?",
"JSON语法规则"
]
];
echo json_encode($arr);
?>
运行结果
{"title":"JSON\u6559\u7a0b","author":"C\u8bed\u8a00\u4e2d\u6587\u7f51","url":"http:\/\/c.biancheng.net\/","catalogue":["JSON\u662f\u4ec0\u4e48\uff1f","JSONP\u662f\u4ec0\u4e48\uff1f","JSON\u8bed\u6cd5\u89c4\u5219"]}
通过运行结果可以看出,在使用 json_encode() 函数将变量转换为 JSON 数据时,会将变量中的中文字符编码为 Unicode 字符(\uXXXX 格式的字符),如果不需要这样的转换,将 json_encode() 函数的第二个参数设置为 JSON_UNESCAPED_UNICODE 即可,如下例所示:
<?php
$arr = [
"title" => "JSON教程",
"author" => "一百减一是零",
"url" => "https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343",
"catalogue" => [
"JSON是什么?",
"JSONP是什么?",
"JSON语法规则"
]
];
echo json_encode($arr,JSON_UNESCAPED_UNICODE );
?>
运行结果
{"title":"JSON教程","author":"C语言中文网","url":"http:\/\/c.biancheng.net\/","catalogue":["JSON是什么?","JSONP是什么?","JSON语法规则"]}
json_decode()
json_decode(string $json, bool $assoc = false, int $depth = 512, int $options = 0): mixed
参数说明如下:
- $json:必填参数,要解析的 JSON 字符串;
- $assoc:可选参数,默认值为 false,若将值设置为 true,那么 json_decode() 函数将返回一个数组;
- $depth:可选参数,用来设置递归的最大深度,默认值为 512,也可以设置为其它大于 0 的值;
- $options:可选参数,默认值为 0,可选值为 JSON_BIGINT_AS_STRING、JSON_INVALID_UTF8_IGNORE、JSON_INVALID_UTF8_SUBSTITUTE、JSON_OBJECT_AS_ARRAY、JSON_THROW_ON_ERROR 等常量,可以同时设置多个常量,常量之间使用竖线
|
进行分隔。有关上述常量的含义,您可以通过 PHP 预定义常量查阅。
若解析成功,json_decode() 函数会返回 JSON 中的数据,若解析失败,或者 JSON 的数据深度超过了递归的限制,则返回 null。
示例
<?php
$str = '{"title":"JSON教程","author":"一百减一是零","url":"https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343","catalogue":["JSON是什么?","JSONP是什么?","JSON语法规则"]}';
echo "<pre>";
var_dump(json_decode($str, true));
?>
运行结果
array(4) {
["title"]=>
string(10) "JSON教程"
["author"]=>
string(16) "一百减一是零"
["url"]=>
string(23) "https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343"
["catalogue"]=>
array(3) {
[0]=>
string(16) "JSON是什么?"
[1]=>
string(17) "JSONP是什么?"
[2]=>
string(16) "JSON语法规则"
}
}
Python
- json.dumps():将 Python 对象转换为 JSON 数据;
- json.loads():将 JSON 数据解析为 Python 对象。
json.dumps()
json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding="utf-8", default=None, sort_keys=False, **kw)
参数说明如下:
- obj:要转换为 JSON 数据的 Python 对象;
- skipkeys:默认值为 False,如果 dict 中 keys 内的数据不是 Python 的基本类型(str、unicode、int、long、float、bool、None),会报 TypeError 错误,若设置为 True,则会跳过这类 key;
- ensure_ascii:默认值 True,即输出 ASCLL 码,若设置为 False,则可以输出中文;
- check_circular:如果值为 False,则跳过对容器类型的循环引用检查,循环引用将导致溢出错误;
- allow_nan:默认值 True,在处理 JSON 规范以外的 Float 类型时(例如:nan、inf、-inf),将其转换为 JavaScript 中的等价类型(例如:NaN、Infinity、-Infinity),若设置为 False,则会引发一个 ValueError 错误,
- cls:用来指定一个自定义的 JSONEncoder 子类,来替换 JSONCoder 类;
- indent:按照给定数值,将数据缩进显示,让数据读起来更加清晰;
- separators:分隔符,分别设置不同 dict 项之间的分隔符和 dict 项内 key 与 value 之间的分隔符,并将冒号
:
与逗号,
之后的空格全部去除;- encoding:设置 JSON 数据的编码方式,默认为 UTF-8;
- default:指定一个函数,当某个对象无法被序列化时会调用该函数;
- sort_keys:若值为 Ture,则表示按照 dict 排序(a 到 z)输出。
示例
import json
dictionary = {"title":"JSON教程","author":"一百减一是零","url":"https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343","catalogue":["JSON是什么?","JSONP是什么?","JSON语法规则"]}
jsonString = json.dumps(dictionary, indent=4, ensure_ascii=False)
print(jsonString)
运行结果
{
"title": "JSON教程",
"author": "一百减一是零",
"url": "https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343",
"catalogue": [
"JSON是什么?",
"JSONP是什么?",
"JSON语法规则"
]
}
json.loads()
json.loads(s[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]])
参数说明如下:
- s:要转换的 JSON 数据,可以是 str、bytes 或 bytearray 等类型;
- encoding:可选参数,设置 JSON 数据的编码方式,默认为 UTF-8;
- cls:可选参数,用于指定一个自定义 JSONCoder 的子类,来替换 JSONCoder 类;
- object_hook:可选参数,将函数的返回值替换为指定的类型,该功能可以用来实现自定义解码器,例如 JSON-RPC;
- parse_float:可选参数,如果指定该参数,那么在解码 JSON 数据时,符合 float 类型的字符串将转换为指定的类型;
- parse_int:可选参数,如果指定该参数,那么在解码 JSON 数据时,符合 int 类型的字符串将转换为指定的类型;
- parse_constant:可选参数,如果指定该参数,那么在解码 JSON 数据时,若出现 -Infinity、Infinity、NaN 等字符串,则调用指定的方法;
- object_pairs_hook:可选参数,将结果以 key-value 有序列表的形式返回,如果 object_hook 和 object_pairs_hook 同时指定的话,优先按照 object_pairs_hook 的设置返回。
示例
import json
json_str = '{"title":"JSON教程","author":"一百减一是零","url":"https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343","catalogue":["JSON是什么?","JSONP是什么?","JSON语法规则"]}'
data = json.loads(json_str)
print(data)
运行结果
{'title': 'JSON教程', 'author': '一百减一是零', 'url': 'https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343', 'catalogue': ['JSON是什么?', 'JSONP是 什么?', 'JSON语法规则']}
Java
import org.json.simple.JSONObject;
class JsonEncodeDemo {
public static void main(String[] args) {
JSONObject obj = new JSONObject();
obj.put("title", "JSON教程");
obj.put("author", "一百减一是零");
obj.put("url", "https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343");
obj.put("hits", 100);
System.out.print(obj);
}
}
运行结果
{"hits":100,"author":"一百减一是零","title":"JSON教程","url":"一百减一是零-CSDN博客"}
使用 Java 解析 JSON 数据
实例
import org.json.simple.JSONObject;
import org.json.simple.JSONArray;
import org.json.simple.parser.ParseException;
import org.json.simple.parser.JSONParser;
class JsonDecodeDemo {
public static void main(String[] args) {
JSONParser parser = new JSONParser();
String s = "[0{\"hits\":100,\"author\":\"一百减一是零\",\"title\":\"JSON教程\",\"url\":\"https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343\"}]";
try{
Object obj = parser.parse(s);
JSONArray array = (JSONArray)obj;
System.out.println(array.get(1));
System.out.println();
}catch(ParseException pe) {
System.out.println("position: " + pe.getPosition());
System.out.println(pe);
}
}
}
运行结果
{"hits":100,"author":"一百减一是零","title":"JSON教程","url":"一百减一是零-CSDN博客"}
Ajax
Ajax 全称“Asynchronous JavaScript and XML”,译为“异步 JavaScript 和 XML”,程序员们习惯称之为“阿贾克斯”,通过 Ajax 我们可以异步在服务器与客户端之间传递数据。在 Ajax 中,普遍使用 JSON 作为传输数据的格式。
<!DOCTYPE html>
<html lang="en">
<head>
<meta content="text/html; charset=utf-8">
<title>AJAX And JSON</title>
<script type="application/javascript">
function load() {
var url = "./data.json"; // 获取 JSON 数据的链接
var request;
if (window.XMLHttpRequest) {
request = new XMLHttpRequest(); //发送 Ajax 请求,适用于 Chrome, mozilla 等浏览器
} else if (window.ActiveXObject) {
request = new ActiveXObject("Microsoft.XMLHTTP"); // 发送 Ajax 请求,适用于 IE 浏览器
}
request.onreadystatechange = function() {
if (request.readyState == 4) {
var jsonObj = JSON.parse(request.responseText); // 解析 JSON 数据
document.getElementById("title").innerHTML = jsonObj.title;
document.getElementById("author").innerHTML = jsonObj.author;
document.getElementById("url").innerHTML = jsonObj.url;
document.getElementById("catalogue").innerHTML = jsonObj.catalogue;
}
}
request.open("GET", url, true);
request.send();
}
</script>
</head>
<body>
Title: <span id="title"></span><br />
Author: <span id="author"></span><br />
Url: <span id="url"></span><br />
Catalogue: <span id="catalogue"></span><br />
<button type="button" onclick="load()">点击加载 JSON 数据</button>
</body>
</html>
date.json 文件中的内容
{
"title": "JSON教程",
"author": "一百减一是零",
"url": "https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343",
"catalogue": [
"JSON是什么?",
"JSONP是什么?",
"JSON语法规则"
]
}
运行结果
扩展知识JSONP是什么?
JSONP 不是一门编程语言,也不是什么特别的技术,它更像一个漏洞,程序员可以利用这个漏洞,实现跨域(可以简单理解为跨域名)传输数据
同源策略
同源策略是由 Netscape(网景)提出的一个著名的安全策略,所有支持 JavaScript 的浏览器都支持这个策略。
所谓同源是指域名、协议、端口都相同。以 http://c.biancheng.net:80/ 为例,c.biancheng.net 为域名,http 为协议,80 为端口(提示:80 为默认端口,可以省略,若为其它端口则必须显示定义)。
为了安全,浏览器不允许进行跨域请求。当我们通过 Ajax 在网页和服务器之间发送或接收数据时,需要保证网页与所请求的地址是同源的,否则无法请求成功。例如 http://c.biancheng.net/ 下的网页,只能与同在 http://c.biancheng.net/ 下的程序进行交互,无法与 https://www.baidu.com/ 下的程序进行交互。
同源策略可以防止 JavaScript 脚本从您的网站中读取数据,并将数据发送到其它的网站。如果没有同源策略,很有可能会有恶意的程序泄露您网站中的内容。
虽然同源策略在一定程度上提高了网站的安全,但也会给程序员带来一些麻烦,例如在访问一些开发接口时,由于同源策略的存在,会调用失败。要解决这种问题就需要用到跨域,跨域的方法有许多种,其中最经典的就是 JSONP。
什么是 JSONP?
JSONP 全称“JSON with Padding”,译为“带回调的 JSON”,它是 JSON 的一种使用模式。通过 JSONP 可以绕过浏览器的同源策略,进行跨域请求。
在进行 Ajax 请求时,由于同源策略的影响,不能进行跨域请求,而<script>
标签的 src 属性却可以加载跨域的 JavaScript 脚本,JSONP 就是利用这一特性实现的。与普通的 Ajax 请求不同,在使用 JSONP 进行跨域请求时,服务器不再返回 JSON 格式的数据,而是返回一段调用某个函数的 JavaScript 代码,在 src 属性种调用,来实现跨域。
JSONP 的优点是兼容性好,在一些老旧的浏览器种也可以运行,但它的缺点也非常明显,那就是只能进行 GET 请求。
如何实现 JSONP
假设我们要从网站 localhost:8080 向服务器 localhost:8081 下的发送请求,并在服务器返回如下内容:
{"name":"一百减一是零", "url":"一百减一是零-CSDN博客"}
如果直接发送 Ajax 请求,由于同源策略的存在,请求会被阻止,因为网站和服务器不同源。示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript</title>
</head>
<body>
<div id="result"></div>
<button type="button" onclick="sendAjax()">发送请求</button>
<script>
function sendAjax() {
// 创建 XMLHttpRequest 对象
var request = new XMLHttpRequest();
// 实例化请求对象
request.open("GET", "http://localhost:8081/test.php");
// 监听 readyState 的变化
request.onreadystatechange = function() {
// 检查请求是否成功
if(this.readyState === 4 && this.status === 200) {
// 将来自服务器的响应插入当前页面
document.getElementById("result").innerHTML = this.responseText;
}
};
// 将请求发送到服务器
request.send();
}
</script>
</body>
</html>
点击页面的“发送请求”按钮,会返回如下错误:
Access to XMLHttpRequest at 'http://localhost:8081/test.php' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
GET http://localhost:8081/test.php net::ERR_FAILED
想要成功从服务器中获取数据,就可以使用我们上面介绍的 JSONP 来实现,实现步骤如下:
使用<script>
标签,将标签的 src 属性设置为要请求的地址,如下所示:
<script src="http://localhost:8081/test.php"></script>
这时您会发现,<script>
标签会自动解析并执行返回的内容,如果这些内容不是完整的 JavaScript 代码,程序就会报错,所有在进行 JSONP 跨域请求时,需要保证服务器返回一段完整的 JavaScript 代码。
另外,返回的内容也不能是一段纯 JSON 的数据,因为 JSON 数据会自动转换为一个 JavaScript 对象,但不将其分配给变量或者传递给函数,我们也无法拿来使用。
因此,我们可以在请求中提供一个回调函数(被作为参数传递的函数,等同于一般函数),然后通过服务器返回这个函数,并将要返回的 JSON 数据作为函数的参数一同返回,这样<script>
标签在解析并执行返回内容是就会自动调用这个函数。示例代码如下:
<script src="http://localhost:8081/test.php?callback=showJsonData"></script>
服务器 http://localhost:8081/ 的完整代码如下所示:
<?php
$data = array('name'=>'一百减一是零', 'url'=>'https://blog.csdn.net/weixin_59383491?spm=1000.2115.3001.5343'); // 定义一个数组,其中包含要返回的内容
$callback = $_GET['callback']; // 接收请求中的回调函数
echo $callback."(".json_encode($data).")"; // 将上面的数组转换为 JSON 格式,然后拼接到函数中,作为函数的参数,返回给前端
return; // 阻止程序向下继续运行
?>
网站 localhost:8080 的完整代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript</title>
</head>
<body>
<script>
function showJsonData(data){
console.log(data);
}
</script>
<script src="http://localhost:8081/test.php?callback=showJsonData"></script>
</body>
</html>
运行结果
{name: '一百减一是零', url: '一百减一是零-CSDN博客'}
总结
通过 JSONP,您可以避开浏览器的同源策略,进行跨域请求。JSONP 是利用 HTML 标签的 src 属性引用资源不受同源策影响的特性来实现的,实现步骤如下:
- 在请求地址中拼接一个回调函数,得到一个新的地址,将这个新地址赋值给 <script> 标签的 src 属性;
- 服务器接收这个回调函数,并向函数中注入参数,然后以字符串的形式返回这个函数以及其中的参数;
- <script> 在接收到返回内容后,会将内容当作是一段 JavaScript 代码,自动执行。
注意:服务器返回的内容,必须是一段可执行的 JavaScript 代码,不能是其它内容。
创作不易,谢谢各位看官大佬的一键三连。
更多推荐
所有评论(0)