当前位置: 首页 > news >正文

【网络编程】网络传输-JSON

一、JSON概述

JSON(JavaScript Object Notation)是一种轻量级、基于文本的数据交换格式,旨在简洁地表示结构化数据,同时兼顾人类可读性和机器解析效率。它起源于 JavaScript 的对象语法,但目前已成为独立于编程语言的通用数据格式,被广泛用于前后端通信、服务间数据交换、配置文件等场景。
在这里插入图片描述

JSON格式主要有以下的特点:

  1. 相比 XML 等格式,JSON 语法简洁(无冗余标签),数据体积更小,传输和解析效率更高。
  2. 基于 Unicode 字符,可直接被人类阅读和编写,便于调试和手动修改。
  3. 几乎所有编程语言(C++、Java、Python、JavaScript 等)都有成熟的 JSON 解析 / 生成库,无需额外适配
  4. 数据结构本身包含字段名,无需额外 schema 即可理解数据含义

二、JSON的语法规则

JSON的语法比较简单,主要是由一个个键值对和有序列表组成,语法规则如下:

2.1 基本结构

  • 对象(Object):表示键值对的集合,用 {} 包裹,键值对之间用逗号 , 分隔。

    • 键(key)必须是字符串,且用双引号 " 包裹(不能用单引号)。
    • 值(value)可以是字符串、数字、布尔值、null、对象或数组。
  • 数组(Array):表示有序的值列表,用 [] 包裹,元素之间用逗号 , 分隔,元素类型可以是任意 JSON 数据类型(包括对象、数组)。

2.2 数据类型

  • 字符串:必须用双引号 " 包裹,支持转义字符(如 \" 表示双引号、\n 表示换行),例如 "name": "Alice"
  • 数字:整数(如 42)、浮点数(如 3.14)、负数(如 -10),不支持八进制 / 十六进制(需用十进制表示)。
  • 布尔值truefalse(小写)。
  • null:表示空值(小写 null)。
  • 对象(Object):嵌套的键值对集合,例如 {"user": {"id": 1, "name": "Bob"}}
  • 数组(Array):有序元素列表,例如 {"hobbies": ["reading", "coding"]}

注意事项

  • 键必须是字符串(双引号包裹),不能是数字或其他类型。
  • 元素之间用逗号分隔,但最后一个元素后不能有逗号(否则会解析错误)。
  • 区分大小写(true 正确,True 错误)。
  • 不支持注释(标准 JSON 语法中无注释,部分扩展格式如 JSON5 支持,但非通用)

2.3 JSON数据结构示例

2.3.1 简单JSON结构

{"name": "张三","age": 25,"isStudent": false,"height": 1.75,"address": null
}

2.3.2 嵌套JSON结构

{"user": {"id": 1001,"info": {"name": "李四","contact": {"phone": "123456789","email": "lisi@example.com"}}}
}

2.3.3 数组(有序列表)

{"fruits": ["apple", "banana", "orange"],"scores": [90, 85.5, 95],"isPass": [true, false, true]
}

2.3.4 复杂JSON结构(数组+嵌套)

{"class": "高三(1)班","students": [{"name": "王五","age": 18,"subjects": ["数学", "英语"]},{"name": "赵六","age": 17,"subjects": ["物理", "化学"]}]
}

三、JSON的使用场景

  1. 数据交换

    • 前后端通信:浏览器与服务器之间的 HTTP 请求 / 响应(如 AJAX、RESTful API),几乎是标准格式。
    • 服务间通信:微服务架构中,不同服务(如 Java 后端与 C++ 服务)通过 JSON 交换数据,避免语言差异导致的兼容性问题。
  2. 配置文件

    • 相比 XML 更轻量,比 INI 更灵活(支持嵌套结构),例如:
{"server": {"port": 8080,"timeout": 30,"log": {"level": "info","path": "/var/log/server.log"}}
}
  1. 数据存储
    部分 NoSQL 数据库(如 MongoDB)直接使用 JSON-like 格式(BSON)存储数据,便于灵活扩展字段。

四、序列化和反序列化JSON

序列化和反序列化JSON有许多成熟的处理库,比如使用C++编程语言可以使用nlohmann/json库,这是一个轻量级的JSON库,风格偏向现代C++,并且只有一个.hpp文件,不需要额外链接库

4.1 下载nlohmann-json

Ubuntu下,可以使用包管理器下载,下载完成后自动安装到系统路径/usr/include

sudo apt update
sudo apt install nlohmann-json3-dev

Windows可以在github上下载源码,手动安装:https://github.com/nlohmann/json/releases

4.2 序列化JSON

我们下面介绍一个例子,用于序列化嵌套的JSON,可以发现,这个库的语法风格十分像STL,对STL熟悉的话就可以自己琢磨出用法,详细手册查看:https://json.nlohmann.me/

  • 可以使用[]来添加对应key-value值,这里会发送自动的类型转换,key一般是std::string类型
  • 或者使用at()函数,这个是返回一个引用,因此可以修改对应的值,并且它具有边界检查
  • 嵌套JSON就是将key设置为JSON类型
  • 初始化JSON类型支持初始化列表的模式
void serializeJson(LoginMsg const& msg,json* pJson){(*pJson)["user"] = msg.user;(*pJson)["password"] = msg.pwd;//嵌套Jsonjson jDate = {{"year",msg.date.year},{"month",msg.date.month},{"day",msg.date.day}};(*pJson)["date"] = jDate;json jTime = {{"hour",msg.time.hour},{"minute",msg.time.min},{"second",msg.time.sec}};(*pJson)["time"]= jTime;std::cout << "===== serialize json =====" << std::endl;    std::cout << pJson->dump(4) << std::endl;
}

序列化好的JSON数据结构可以使用dump成员函数来打印,其中dump(4)表示设置4位的缩进值

{"date": {"day": 20,"month": 7,"year": 2025},"password": "xx123456789","time": {"hour": 14,"minute": 30,"second": 15},"user": "Antonio"
}

4.3 反序列化JSON

  • 反序列化JSON可以从json类中像STLmap一样通过[]at()访问,与上述序列化一致
  • 不论是[]还是at(),都是返回一个json的引用,因此支持链式调用,用起来很方便
void deserializeJson(json* pJson){std::cout << "===== deserialize json =====" << std::endl;std::string user = pJson->at("user");std::string password = pJson->at("password");Date date;date.year = pJson->at("date").at("year");date.month = pJson->at("date").at("month");date.day = pJson->at("date").at("day");Time time;time.hour = pJson->at("time").at("hour");time.min = pJson->at("time").at("minute");time.sec = pJson->at("time").at("second");std::cout << "user = " << user << std::endl;std::cout << "password = " << password << std::endl;std::cout << "date = [" << " year = " << date.year << " month = " << date.month << " day = " << date.day <<" ]" << std::endl;;std::cout << "time = [" << " hour = " << time.hour << " minute = " << time.min << " second = " << time.sec << " ]" << std::endl; 
}

4.4 测试结果

完整的测试代码如下

#include<iostream>
#include<nlohmann/json.hpp>using json = nlohmann::json;struct Date{int year;int month;int day;
};struct Time{int hour;int min;int sec;
};struct LoginMsg{std::string user;std::string pwd;Date date;Time time;};void serializeJson(LoginMsg const& msg,json* pJson){(*pJson)["user"] = msg.user;(*pJson)["password"] = msg.pwd;//嵌套Jsonjson jDate = {{"year",msg.date.year},{"month",msg.date.month},{"day",msg.date.day}};(*pJson)["date"] = jDate;json jTime = {{"hour",msg.time.hour},{"minute",msg.time.min},{"second",msg.time.sec}};(*pJson)["time"]= jTime;std::cout << "===== serialize json =====" << std::endl;    std::cout << pJson->dump(4) << std::endl;
}void deserializeJson(json* pJson){std::cout << "===== deserialize json =====" << std::endl;std::string user = pJson->at("user");std::string password = pJson->at("password");Date date;date.year = pJson->at("date").at("year");date.month = pJson->at("date").at("month");date.day = pJson->at("date").at("day");Time time;time.hour = pJson->at("time").at("hour");time.min = pJson->at("time").at("minute");time.sec = pJson->at("time").at("second");std::cout << "user = " << user << std::endl;std::cout << "password = " << password << std::endl;std::cout << "date = [" << " year = " << date.year << " month = " << date.month << " day = " << date.day <<" ]" << std::endl;;std::cout << "time = [" << " hour = " << time.hour << " minute = " << time.min << " second = " << time.sec << " ]" << std::endl; 
}int main(){std::string user = "Antonio";std::string password = "xx123456789";Date date = {2025,7,20};Time time = {14,30,15};LoginMsg loginMsg = {user,password,date,time};json* pJLoginMsg = new json();serializeJson(loginMsg,pJLoginMsg);deserializeJson(pJLoginMsg);delete pJLoginMsg;return 0;
}

序列化JSON和反序列化JSON的测试输出结果如下:

在这里插入图片描述

更多资料:https://github.com/0voice

http://www.dtcms.com/a/289492.html

相关文章:

  • 【C语言】字符串与字符函数详解(下)
  • Shell脚本-cut工具
  • 从零到一MCP快速入门实战【1】
  • 疯狂星期四第13天运营日报
  • Java拓扑排序:2115 从给定原材料中找到所有可以做出的菜
  • Linux 基本指令详解
  • Self-Consistency:跨学科一致性的理论与AI推理的可靠性基石
  • WebDriver 对象中的方法
  • C++STL系列之list
  • Vue DIY 内容文本超出组件
  • Numpy库,矩阵形状与维度操作
  • 矩阵算法题
  • ZYNQ创新实践:免IIC驱动直控MCP4661T数字电位器
  • ollama基本配置
  • 仙盟数据库应用-外贸标签打印系统 前端数据库-V8--毕业论文-—-—仙盟创梦IDE
  • 数据库操作丨C++ 操作 数据库——SQLServer 篇
  • 数据库技术总结
  • 激光雷达和相机在线标定
  • 试用SAP BTP 06:AI服务-Data Attribute Recommendation
  • Java行为型模式---解释器模式
  • 30天打牢数模基础-XgBoost讲解
  • 第四章第一节 OLED 调试工具
  • 【LeetCode 热题 100】200. 岛屿数量——DFS
  • 20250720-3-Kubernetes 调度-资源限制对Pod调度的影响(2)_笔记
  • 隧道无线调频广播与“群载波”全频插播技术在张石高速黑石岭隧道中的应用
  • 数据结构第二章:线性表之顺序表
  • Kubernetes (K8S)知识详解
  • 【k8s集群管理平台】k8s运维管理的新玩法,让运维电脑随时不离身的现状成为过去
  • 【论文研读】SlowFast Networks for Video Recognition
  • 2024年全国青少年信息素养大赛Scratch算法创意实践挑战赛 小高组 初赛 真题