JSON基础知识与实践:轻松理解并应用JSON格式
- 一、简介
- 二、JSON的基本结构
- 2.1、JSON对象
- 2.2、JSON数组
- 2.3、JSON键-值对
- 2.4、JSON数据类型
- 三、JSON格式规范
- 3.1、JSON的语法规则
- 3.2、JSON的数据表示
- 3.3、JSON的格式化与美化
- 四、JSON与编程语言
- 4.1、JSON的序列化和反序列化
- 4.2、C++ JSON库的使用示例
- 五、常见的JSON格式错误
- 六、总结
一、简介
JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式,它是基于JavaScript语言的子集,但是独立于编程语言的文字格式。JSON格式易于阅读和编写,同时也易于机器解析和生成。它常用于前端和后端之间的数据交换以及存储配置信息。JSON数据由键值对构成,可以表示对象和数组。由于其简洁性和易用性,JSON已经成为了互联网上常用的数据交换格式之一。
JSON(JavaScript Object Notation)最早由道格拉斯·克罗克福德(Douglas Crockford)在2001年提出。JSON最初是为了解决XML(可扩展标记语言)在数据交换中的繁琐和过于复杂的问题而设计的。
JSON的发展经历:
- 2001年,道格拉斯·克罗克福德提出了JSON的概念,而且很快就得到了广泛的应用和支持。
- 随着Web应用和移动应用的兴起,JSON作为一种数据交换格式得到了广泛应用,尤其是在前后端数据传输以及API设计中。
- JSON在发展过程中被广泛接受,最终成为一种国际标准。目前,JSON的标准由ECMA国际组织发布,称为ECMA-404标准。
JSON的优点:
- 易读性: JSON使用键值对的方式表示数据,易于阅读和编辑。
- 易解析性: JSON格式简单,易于解析和转换成数据对象,适合用于前后端数据交换。
- 跨语言性: JSON是一种独立于编程语言的数据格式,可以在各种编程语言中使用和解析。
- 数据量小: JSON数据量轻量,适合网络传输,响应速度快。
- 可嵌套性: JSON支持嵌套对象和数组,可以表示复杂结构的数据。
JSON的应用场景:
- Web开发: 在前后端交互中,常用JSON格式传输数据,如通过AJAX请求获取数据。
- API设计: JSON常用于设计RESTful API,作为数据交换格式,方便不同应用之间数据交互。
- 配置文件: JSON格式适合用于存储配置信息,如项目配置、数据映射等。
- 移动应用开发: 在移动应用中,常用JSON格式作为数据交互的标准格式,例如移动端与服务器接口的数据交互。
二、JSON的基本结构
2.1、JSON对象
JSON(JavaScript Object Notation)对象是 JSON 中最常用的一种结构。它由大括号 {} 包裹,包含一组键值对,每个键值对之间通过逗号分隔。
JSON 对象的基本结构:
{
"key1": "value1",
"key2": "value2",
"key3": "value3"
}
每个键值对由键(key)和值(value)组成,用冒号分隔。键是一个字符串,用双引号括起来,然后是冒号,而值可以是字符串、数值、布尔值、数组、甚至是另一个JSON对象。
示例:
{
"id": 1,
"name": "Lion Long",
"email": "2505756506@qq.com",
"age": 18,
"is_active": true,
"hobbies": ["hiking", "reading", "coding"],
"address": {
"city": "shengzhen",
"zip": "10001"
}
}
JSON对象是一个灵活且强大的数据结构,用于表示和交换数据,常见于前后端之间的数据传输以及存储配置信息等多种应用场景。
2.2、JSON数组
JSON数组是JSON中另一个常用的结构,它由中括号 []
包裹,包含了一组值,值之间通过逗号分隔。
JSON数组的基本结构:
["apple", "banana", "orange", "grape"]
数组中的每个元素都是一个值,可以是字符串、数值、布尔值、数组或者是另一个JSON对象。
示例:
[
{
"name": "John",
"age": 30,
"city": "New York"
},
{
"name": "Jane",
"age": 25,
"city": "Los Angeles"
}
]
JSON数组在实际应用中常用于表示多个元素的列表,比如在前端中存储一组数据,或者在后端API中返回一组数据。
JSON数组也可以嵌套在JSON对象中,或者JSON对象可以作为数组的元素,这样可用来表示更加复杂的数据结构。
2.3、JSON键-值对
JSON键值对是 JSON 中最基本的结构之一。它表示了一个键(key)和对应的值(value)之间的关系。
JSON键值对的结构:
"key": "value"
“key” 是键,它必须是一个字符串,用双引号括起来。然后是冒号(:)分隔键和值。 “value” 可以是字符串、数值、布尔值、数组、甚至是另一个JSON对象。
示例:
"name": "Lion Long"
JSON键值对通常用在 JSON 对象中,对于JSON数组,只包含值,没有显式的键。 JSON键值对也在许多地方得到了广泛的应用,比如配置文件、API数据格式等。
2.4、JSON数据类型
JSON支持以下几种基本数据类型:
- 字符串:用双引号括起来的文本数据,例如 “Hello, World”。
- 数值:整数或浮点数,例如 42 或 3.14。
- 布尔值:true 或 false。
- 数组:由方括号包围的、以逗号分隔的值的有序列表。例如 [1, 2, 3]。
- 对象:由花括号包围的、由键值对组成的无序集合。例如 {“name”: “John”, “age”: 30}。
- 空值:null 表示一个空值。
JSON支持这些组合的嵌套数据结构,可以创建更为复杂和层次分明的数据格式。
JSON的这些基本数据类型以及它们的组合和嵌套构成了JSON的灵活性和表达能力,使得它成为了现代应用程序中常用的数据交换格式。
三、JSON格式规范
3.1、JSON的语法规则
- 键值对必须用双引号括起来,即键必须是一个字符串。
- 键和值之间使用冒号分隔。
- 多个键值对之间使用逗号分隔。
- 对象的表示使用花括号括起来,如 {}。
- 数组的表示使用方括号括起来,如 []。
- 字符串可以包含转义字符,比如 \n 表示换行,\t 表示制表符等。
- 字符串必须使用双引号,不能使用单引号。
- 数值可以是整数或浮点数,不需要使用引号包裹。
- 布尔值只能是 true 或 false,不需要使用引号包裹。
- 空值使用 null 表示,也不需要使用引号包裹。
示例:
{
"name": "Lion Long",
"age": 30,
"isStudent": false,
"grades": [90, 85, 75],
"address": {
"street": "123 Main St",
"city": "fly"
},
"email": null
}
3.2、JSON的数据表示
-
对象表示:使用花括号 {} 来表示一个对象,对象由一组键值对构成,键和值之间使用冒号
:
分隔,键值对之间使用逗号 , 分隔。例如:{“name”: “John”, “age”: 30, “isStudent”: false} -
数组表示:使用方括号 [] 来表示一个数组,数组由一组值构成,值之间使用逗号 , 分隔。例如:[1, 2, 3, 4]
-
字符串表示:使用双引号 " " 包裹的一组字符序列,可以包含转义字符,例如:“Hello, World”
-
数值表示:表示整数或浮点数,可以使用科学计数法表示,例如:42, 3.14, 1.23e+10
-
布尔值表示:true 或 false,不需要使用引号包裹。
-
空值表示:使用 null 表示,也不需要使用引号包裹。
JSON 的数据表示能够清晰地表达各种数据类型和数据结构,具有很好的可读性和可扩展性,同时也很好地支持各种编程语言的解析和序列化。
3.3、JSON的格式化与美化
JSON 的格式化与美化是指将 JSON 数据按照一定的格式排列,使其更易于阅读和理解。在实际应用中,由于计算机生成的 JSON 数据通常是压缩且无结构的,因此进行格式化和美化可以更清晰地查看和编辑 JSON 数据。
-
缩进:为了使 JSON 结构更加清晰,通常会对 JSON 数据进行适当的缩进,使不同层级的数据之间有明显的缩进间隔,方便阅读和理解。
-
换行:适当的换行可以使 JSON 数据更加易读,避免一行数据过长而难以阅读的情况。
-
空格:在适当的位置使用空格,使 JSON 数据看起来更整洁和易读。
未格式化的 JSON 数据:
{"name":"Lion","age":30,"isStudent":false,"grades":[90,85,75],"address":{"street":"123 Main St","city":"fly"},"email":null}
经过格式化和美化后的 JSON 数据:
{
"name": "Lion",
"age": 30,
"isStudent": false,
"grades": [90, 85, 75],
"address": {
"street": "123 Main St",
"city": "fly"
},
"email": null
}
可以看到,格式化和美化后的 JSON 数据更易于阅读和理解,每个键值对都有明显的缩进,不同的数据元素之间使用换行分隔,整体结构更加清晰。
四、JSON与编程语言
JavaScript:JSON 最初就是在 JavaScript 中诞生的,JSON 与 JavaScript 对象字面量的语法非常相似,因此在 JavaScript 中非常自然地支持 JSON。可以使用内置的 JSON
对象来解析和序列化 JSON 数据。
// 解析 JSON
var jsonString = '{"name": "John", "age": 30}';
var jsonObject = JSON.parse(jsonString);
// 序列化为 JSON
var person = {name: "John", age: 30};
var jsonString = JSON.stringify(person);
Python:Python 语言内置了一个名为 json
的库,可以用于解析和生成 JSON 数据。
import json
# 解析 JSON
jsonString = '{"name": "John", "age": 30}'
jsonObject = json.loads(jsonString)
# 生成 JSON
person = {'name': 'John', 'age': 30}
jsonString = json.dumps(person)
在 C++ 中,通常使用第三方库来处理 JSON 数据,因为标准 C++ 库并不提供原生的 JSON 解析和生成功能。RapidJSON 和 nlohmann/json 是两个常用的第三方库来解析和生成 JSON 数据。
4.1、JSON的序列化和反序列化
JSON 的序列化和反序列化是指将数据结构转换为 JSON 格式的字符串,以及将 JSON 字符串转换为对应的数据结构的过程。在许多编程语言中,都有内置或第三方库来实现 JSON 的序列化和反序列化操作。
序列化示例(将数据结构转换为 JSON 字符串):
// JavaScript
var person = {name: "Lion", age: 30};
var jsonString = JSON.stringify(person);
console.log(jsonString); // 输出: {"name": "Lion", "age": 30}
// Python
import json
person = {'name': 'Lion', 'age': 30}
jsonString = json.dumps(person)
print(jsonString) # 输出: {"name": "Lion", "age": 30}
// C++
// Using RapidJSON library
rapidjson::Document document;
document.SetObject();
rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
document.AddMember("name", "Lion", allocator);
document.AddMember("age", 30, allocator);
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
document.Accept(writer);
std::string jsonString = buffer.GetString();
std::cout << jsonString << std::endl; // 输出: {"name": "Lion", "age": 30}
反序列化示例(将 JSON 字符串转换为数据结构):
// JavaScript
var jsonString = '{"name": "Lion", "age": 30}';
var person = JSON.parse(jsonString);
console.log(person.name); // 输出: Lion
console.log(person.age); // 输出: 30
// Python
import json
jsonString = '{"name": "Lion", "age": 30}'
person = json.loads(jsonString)
print(person['name']) # 输出: Lion
print(person['age']) # 输出: 30
// C++
// Using RapidJSON library
rapidjson::Document document;
document.Parse(jsonString.c_str());
std::string name = document["name"].GetString();
int age = document["age"].GetInt();
std::cout << name << std::endl; // 输出: Lion
std::cout << age << std::endl; // 输出: 30
流程图:
4.2、C++ JSON库的使用示例
在 C++需要使用第三方库来处理 JSON 数据,因为标准 C++ 库并不提供原生的 JSON 解析和生成功能。
(1)使用 RapidJSON 库:RapidJSON 是一个快速的 C++ JSON 解析/生成库,它提供了一种方便的方式来解析和生成 JSON 数据。
下载RapidJSON 库:
git clone https://github.com/Tencent/rapidjson.git
或者通过直接下载 zip 压缩文件方式:
wget https://github.com/Tencent/rapidjson/archive/master.zip
unzip master.zip
RapidJSON 是一个头文件库,因此不需要编译和安装过程。只需将 RapidJSON 的头文件复制到项目中,并添加头文件路径到 C++ 编译器的 include 目录。
解析 JSON 数据:
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
// JSON 字符串
const char* jsonString = "{\"name\": \"Lion\", \"age\": 30}";
// 解析 JSON
rapidjson::Document document;
document.Parse(jsonString);
// 读取解析后的数据
std::string name = document["name"].GetString();
int age = document["age"].GetInt();
生成 JSON 数据:
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
// 创建 JSON 对象
rapidjson::Document document;
document.SetObject();
rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
// 添加数据
rapidjson::Value name;
name.SetString("Lion");
document.AddMember("name", name, allocator);
rapidjson::Value age;
age.SetInt(30);
document.AddMember("age", age, allocator);
// 生成 JSON 字符串
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
document.Accept(writer);
std::string jsonString = buffer.GetString();
(2)使用 nlohmann/json 库:nlohmann/json 是一个现代 C++ 库,提供了便捷的 JSON 解析/生成功能,并支持 STL 类型的互操作。
下载 nlohmann/json 库:
git clone https://github.com/nlohmann/json.git
或者通过直接下载 zip 压缩文件方式:
wget https://github.com/nlohmann/json/archive/refs/heads/develop.zip
unzip develop.zip
nlohmann/json 是一个单头文件库(即仅有一个头文件),因此不需要编译和安装过程。
解析 JSON 数据:
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// JSON 字符串
std::string jsonString = "{\"name\": \"Lion\", \"age\": 30}";
// 解析 JSON
json jsonObject = json::parse(jsonString);
// 读取解析后的数据
std::string name = jsonObject["name"];
int age = jsonObject["age"];
生成 JSON 数据:
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// 创建 JSON 对象
json jsonObject;
// 添加数据
jsonObject["name"] = "Lion";
jsonObject["age"] = 30;
// 生成 JSON 字符串
std::string jsonString = jsonObject.dump();
五、常见的JSON格式错误
(1)键名和字符串值必须使用双引号:“key”: “value”。
错误示例:
{
key: "value"
}
修正:
{
"key": "value"
}
(2)数组或对象中的元素末尾不能带有逗号。
错误示例:
{
"array": [1, 2, 3,]
}
修正:
{
"array": [1, 2, 3]
}
(3)保证数据类型的一致性.
错误示例:
{
"numberValue": "10",
"boolValue": "true"
}
修正:
{
"numberValue": 10,
"boolValue": true
}
(4)在嵌套对象和数组时,确保括号和括号的对应关系。
错误示例:
{
"object": {
"key1": "value1"
],
"array": [1, 2, 3
}
修正:
{
"object": {
"key1": "value1"
},
"array": [1, 2, 3]
}
(5)使用合适的转义字符处理特殊字符和换行符。
错误示例:
{
"text": "This is a multi-line
string"
}
修正:
{
"text": "This is a multi-line\nstring"
}
最好的方式是在生成JSON数据时使用JSON解析器/字符串构建器/序列化器等工具,以确保生成的数据格式正确。在接受和处理JSON数据时,也需要使用合适的JSON解析器来解析数据,避免手动操作JSON字符串。这样可以减少由手动操作JSON字符串带来的潜在错误。同时,通过对数据的验证和测试,也可以更好地确保数据的正确性和一致性。
六、总结
JSON(JavaScript Object Notation)作为一种轻量级的数据交换格式,在现代Web开发中具有重要的地位和广泛的应用前景。
-
简洁性和可读性。
-
跨平台和跨语言性。
-
JSON格式支持多种类型的数据,包括字符串、数字、布尔值、数组、对象等,同时也可以嵌套使用。
-
客户端和服务器通信。
基于以上特点,JSON在各种技术领域中都得到了广泛的应用,包括Web开发、移动应用开发、大数据处理、物联网、云计算等领域。