文章目录
- json中的常见数据结构
-
-
- 一、基础数据类型(原子结构)
- 二、核心复合结构
-
- [1. JSON对象(Object)](#1. JSON对象(Object))
- [2. JSON数组(Array)](#2. JSON数组(Array))
- 三、常见组合结构(实际开发高频)
-
- [1. "对象+数组":列表型数据](#1. “对象+数组”:列表型数据)
- [2. "数组+对象":纯列表数据](#2. “数组+对象”:纯列表数据)
- [3. 嵌套对象:多层级数据](#3. 嵌套对象:多层级数据)
- [4. 数组嵌套数组:多维数据](#4. 数组嵌套数组:多维数据)
- 四、关键注意事项
- 总结
-
- jsoncpp数据结构
-
-
- 一、核心基础类:Json::Value
-
- [1. Json::Value的类型枚举(对应JSON基础类型)](#1. Json::Value的类型枚举(对应JSON基础类型))
- [2. Json::Value的核心操作方法](#2. Json::Value的核心操作方法)
- 二、JsonCpp核心数据结构(对应JSON复合结构)
-
- [1. JSON对象 → Json::Value(objectValue类型)](#1. JSON对象 → Json::Value(objectValue类型))
- [2. JSON数组 → Json::Value(arrayValue类型)](#2. JSON数组 → Json::Value(arrayValue类型))
- [3. 嵌套结构(对象嵌套对象/数组)](#3. 嵌套结构(对象嵌套对象/数组))
- 三、辅助核心类(解析/序列化)
- 四、关键注意事项
- 总结
-
json中的常见数据结构
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,基于JavaScript对象语法,但独立于编程语言,其核心是通过键值对组织数据,支持多种基础数据结构和复合结构。以下是JSON中最常见的数据结构,结合示例和特点详细说明:
一、基础数据类型(原子结构)
JSON的基础类型是构成复杂结构的最小单元,共6种核心类型:
| 类型 | 说明 | 示例 |
|---|---|---|
| 字符串 | 双引号包裹的Unicode字符,支持转义(\"/\\/\//\b/\f/\n/\r/\t/\uXXXX) |
"name": "张三" |
| 数字 | 整数、浮点数,支持负数、科学计数法(无八进制/十六进制) | "age": 25, "price": 99.9, "count": 1e3 |
| 布尔值 | 仅true/false(小写,无引号) |
"isStudent": true |
| null | 表示空值(小写,无引号) | "address": null |
| 对象 | 键值对的无序集合(复合类型,下文详细说明) | {"id": 1, "name": "李四"} |
| 数组 | 有序的值列表(复合类型,下文详细说明) | ["苹果", "香蕉", 3.14] |
注意:JSON中不支持 undefined、函数、日期(需转为字符串/数字)、正则表达式等JavaScript特有的类型。
二、核心复合结构
1. JSON对象(Object)
- 定义 :以
{}包裹的无序键值对集合,键必须是双引号包裹的字符串,值可以是任意JSON基础类型/复合类型。 - 语法规则 :
- 键值对之间用
,分隔,最后一个键值对后不能加逗号(否则解析报错); - 键和值之间用
:分隔; - 键必须是字符串(单引号/无引号均不合法)。
- 键值对之间用
- 示例:
json
{
"id": 1001,
"userInfo": {
"username": "zhangsan",
"email": "zhangsan@example.com"
},
"hobbies": ["篮球", "阅读"],
"isVip": false,
"score": null
}
- 特点 :
- 无序性:键值对的顺序不影响解析(不同解析器可能保留顺序,但标准不保证);
- 嵌套性:值可以是另一个JSON对象(实现多层数据结构)。
2. JSON数组(Array)
- 定义 :以
[]包裹的有序值列表,值可以是任意JSON基础类型/复合类型(数组元素类型可不同)。 - 语法规则 :
- 元素之间用
,分隔,最后一个元素后不能加逗号; - 数组长度可通过索引获取(从0开始)。
- 元素之间用
- 示例:
json
[
101,
"李四",
{"age": 28, "city": "北京"},
[1.80, 75.5],
true,
null
]
- 典型场景:表示列表数据(如用户列表、商品列表):
json
{
"students": [
{"id": 1, "name": "小明", "grade": 90},
{"id": 2, "name": "小红", "grade": 95}
]
}
- 特点 :
- 有序性:元素顺序固定,可通过索引访问;
- 异构性:数组内可混合不同类型的值(如数字、字符串、对象)。
三、常见组合结构(实际开发高频)
1. "对象+数组":列表型数据
最常用的结构,外层是对象(包含元信息),内层数组存放具体列表项:
json
{
"code": 200, // 状态码
"msg": "请求成功", // 提示信息
"data": { // 数据体
"total": 100, // 总条数
"list": [ // 列表数据
{"id": 1, "name": "商品1", "price": 99},
{"id": 2, "name": "商品2", "price": 199}
]
}
}
2. "数组+对象":纯列表数据
直接返回数组,每个元素是对象(适用于简单列表):
json
[
{"date": "2026-01-01", "temperature": 10},
{"date": "2026-01-02", "temperature": 12}
]
3. 嵌套对象:多层级数据
对象的值是另一个对象,实现数据的层级划分:
json
{
"user": {
"basic": {
"name": "王五",
"age": 30
},
"contact": {
"phone": "13800138000",
"address": {
"province": "广东",
"city": "深圳"
}
}
}
}
4. 数组嵌套数组:多维数据
适用于矩阵、坐标等场景:
json
{
"matrix": [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
],
"points": [[10, 20], [30, 40], [50, 60]]
}
四、关键注意事项
- 语法严格性 :
- 键必须用双引号(
{"name": "张三"}合法,{name: "张三"}/{'name': '张三'}不合法); - 末尾不能有多余逗号(如
[1,2,]/{"a":1,}解析报错); - 数字不能以0开头(除0本身,如
0123不合法);
- 键必须用双引号(
- 空结构 :空对象
{}、空数组[]是合法的,常用于默认值; - 解析兼容性 :所有主流编程语言(Java/Python/Go/JavaScript等)都有JSON解析库,可将JSON字符串转为对应语言的对象/数组(如JavaScript的
JSON.parse(),Python的json.loads())。
总结
JSON的核心是对象(无序键值对) 和数组(有序值列表) 两大复合结构,结合字符串、数字、布尔值、null四种基础类型,可灵活组合出各种复杂数据形态,是前后端交互、配置文件、数据存储的首选格式。实际开发中,最常用的是"对象包裹数组"的列表结构,需严格遵守JSON语法规则以避免解析错误。
jsoncpp数据结构
JsonCpp是C++中最常用的JSON解析/序列化库,其核心围绕Json::Value (表示任意JSON值)和辅助类(如Json::Reader/Json::Writer)构建,所有JSON数据结构最终都映射为Json::Value的不同类型。以下是JsonCpp中核心数据结构、用法及对应JSON结构的映射关系,结合示例详细说明:
一、核心基础类:Json::Value
Json::Value是JsonCpp的核心,可表示JSON支持的所有数据类型(字符串、数字、布尔、null、对象、数组),是一个"万能容器",通过类型区分和方法调用操作不同JSON结构。
1. Json::Value的类型枚举(对应JSON基础类型)
JsonCpp通过Json::ValueType枚举定义了Json::Value的类型,与JSON原生类型一一对应:
| Json::ValueType枚举值 | 对应JSON类型 | 说明 | 示例初始化 |
|---|---|---|---|
nullValue |
null | 空值 | Json::Value val;(默认null) |
intValue |
整数 | 32位整数(超出用uintValue/realValue) |
Json::Value val(100); |
uintValue |
无符号整数 | 无符号32位整数 | Json::Value val((unsigned int)200); |
realValue |
浮点数 | 双精度浮点数 | Json::Value val(3.1415); |
stringValue |
字符串 | UTF-8字符串 | Json::Value val("hello json"); |
booleanValue |
布尔值 | true/false | Json::Value val(true); |
arrayValue |
数组 | 有序值列表 | Json::Value val(Json::arrayValue); |
objectValue |
对象 | 无序键值对(键为字符串) | Json::Value val(Json::objectValue); |
2. Json::Value的核心操作方法
| 操作类型 | 方法示例 | 说明 |
|---|---|---|
| 类型判断 | val.isNull()/val.isInt()/val.isArray() |
判断当前Value的类型 |
| 取值(基础类型) | val.asInt()/val.asString()/val.asBool() |
转为对应C++类型(类型不匹配返回默认值) |
| 数组操作 | val.append(123)/val[0]/val.size() |
追加元素、索引访问、获取数组长度 |
| 对象操作 | val["name"] = "张三"/val.get("age", 0) |
键值赋值、按键取值(无则返回默认值) |
| 遍历(对象) | Json::Value::Members keys = val.getMemberNames() |
获取所有键名,遍历键值对 |
| 遍历(数组) | for (int i=0; i<val.size(); i++) { val[i]; } |
按索引遍历数组元素 |
二、JsonCpp核心数据结构(对应JSON复合结构)
1. JSON对象 → Json::Value(objectValue类型)
- 映射关系 :JSON对象
{"key": value}对应Json::Value的objectValue类型,通过字符串键访问值。 - 示例代码:
cpp
#include <json/json.h>
#include <iostream>
int main() {
// 1. 构建JSON对象
Json::Value user(Json::objectValue);
user["id"] = 1001; // intValue
user["name"] = "张三"; // stringValue
user["isVip"] = true; // booleanValue
user["score"] = Json::nullValue; // nullValue
user["price"] = 99.9; // realValue
// 2. 访问对象值
std::cout << "ID: " << user["id"].asInt() << std::endl;
std::cout << "Name: " << user["name"].asString() << std::endl;
// 安全取值(键不存在时返回默认值0)
std::cout << "Age: " << user.get("age", 0).asInt() << std::endl;
// 3. 遍历对象所有键值对
Json::Value::Members keys = user.getMemberNames();
for (const auto& key : keys) {
std::cout << key << ": " << user[key] << std::endl;
}
return 0;
}
-
输出:
ID: 1001
Name: 张三
Age: 0
id: 1001
name: "张三"
isVip: true
score: null
price: 99.9
2. JSON数组 → Json::Value(arrayValue类型)
- 映射关系 :JSON数组
[v1, v2, v3]对应Json::Value的arrayValue类型,通过索引访问元素(索引从0开始)。 - 示例代码:
cpp
#include <json/json.h>
#include <iostream>
int main() {
// 1. 构建JSON数组
Json::Value hobbies(Json::arrayValue);
hobbies.append("篮球"); // 追加字符串
hobbies.append("阅读"); // 追加字符串
hobbies.append(25); // 追加整数
hobbies.append(3.14); // 追加浮点数
// 2. 访问数组元素
std::cout << "数组长度: " << hobbies.size() << std::endl;
std::cout << "第一个元素: " << hobbies[0].asString() << std::endl;
std::cout << "第四个元素: " << hobbies[3].asDouble() << std::endl;
// 3. 遍历数组
for (int i = 0; i < hobbies.size(); ++i) {
std::cout << "索引" << i << ": " << hobbies[i] << std::endl;
}
return 0;
}
-
输出:
数组长度: 4
第一个元素: 篮球
第四个元素: 3.14
索引0: "篮球"
索引1: "阅读"
索引2: 25
索引3: 3.14
3. 嵌套结构(对象嵌套对象/数组)
实际开发中最常用的组合,对应JSON的嵌套结构,核心是Json::Value的嵌套赋值。
- 示例:对象嵌套对象+数组
cpp
#include <json/json.h>
#include <iostream>
#include <string>
int main() {
// 外层对象
Json::Value root(Json::objectValue);
root["code"] = 200;
root["msg"] = "请求成功";
// 内层数据对象
Json::Value data(Json::objectValue);
data["total"] = 2;
// 内层数组(列表数据)
Json::Value list(Json::arrayValue);
// 数组元素1
Json::Value item1(Json::objectValue);
item1["id"] = 1;
item1["name"] = "商品1";
item1["price"] = 99.9;
list.append(item1);
// 数组元素2
Json::Value item2(Json::objectValue);
item2["id"] = 2;
item2["name"] = "商品2";
item2["price"] = 199.9;
list.append(item2);
// 组装嵌套结构
data["list"] = list;
root["data"] = data;
// 序列化输出(美化格式)
Json::StyledWriter writer;
std::string jsonStr = writer.write(root);
std::cout << jsonStr << std::endl;
return 0;
}
- 输出(格式化后的JSON):
json
{
"code" : 200,
"msg" : "请求成功",
"data" : {
"total" : 2,
"list" : [
{
"id" : 1,
"name" : "商品1",
"price" : 99.9
},
{
"id" : 2,
"name" : "商品2",
"price" : 199.9
}
]
}
}
三、辅助核心类(解析/序列化)
JsonCpp的"数据结构"不仅包含Json::Value,还包括用于解析JSON字符串、序列化Json::Value的辅助类:
| 类名 | 作用 | 核心方法 |
|---|---|---|
Json::Reader |
解析JSON字符串为Json::Value |
bool parse(const std::string& jsonStr, Json::Value& root) |
Json::Writer |
抽象类,序列化Json::Value为字符串 |
子类实现std::string write(const Json::Value& root) |
Json::FastWriter |
轻量级序列化(无格式化,单行字符串) | 继承Writer,输出紧凑JSON |
Json::StyledWriter |
美化序列化(带缩进、换行) | 继承Writer,输出易读的格式化JSON |
Json::StyledStreamWriter |
流式美化序列化(直接写入流) | void write(std::ostream& os, const Json::Value& root) |
示例:解析JSON字符串为Json::Value
cpp
#include <json/json.h>
#include <iostream>
#include <string>
int main() {
// JSON字符串
std::string jsonStr = R"({
"name": "李四",
"age": 28,
"hobbies": ["游泳", "跑步"],
"isMarried": false
})";
// 解析器
Json::Reader reader;
Json::Value root;
// 解析JSON字符串
if (!reader.parse(jsonStr, root)) {
std::cerr << "解析失败: " << reader.getFormattedErrorMessages() << std::endl;
return 1;
}
// 访问解析后的数据
std::cout << "姓名: " << root["name"].asString() << std::endl;
std::cout << "年龄: " << root["age"].asInt() << std::endl;
std::cout << "第一个爱好: " << root["hobbies"][0].asString() << std::endl;
return 0;
}
四、关键注意事项
- 类型安全 :
- 调用
asInt()/asString()等方法时,需确保Json::Value的类型匹配(如nullValue调用asInt()会返回0,无报错但可能逻辑异常); - 建议先通过
isInt()/isString()等判断类型,再取值。
- 调用
- 空值处理 :
- 默认构造的
Json::Value是nullValue,可通过isNull()判断; - 访问不存在的键/索引时,会返回一个
nullValue的Json::Value(而非崩溃)。
- 默认构造的
- 编码问题 :
- JsonCpp默认处理UTF-8编码,若JSON字符串是GBK/GB2312,需先转换为UTF-8再解析。
- 版本差异 :
-
JsonCpp 1.9.x+ 推荐使用
Json::CharReader/Json::CharReaderBuilder替代Json::Reader(Reader已标记为过时),示例:cppJson::CharReaderBuilder builder; std::unique_ptr<Json::CharReader> reader(builder.newCharReader()); std::string err; bool ok = reader->parse(jsonStr.c_str(), jsonStr.c_str()+jsonStr.size(), &root, &err);
-
总结
JsonCpp的核心数据结构是Json::Value,它通过不同类型(objectValue/arrayValue/intValue等)映射JSON的所有原生结构,配合Reader(解析)和Writer(序列化)类,实现JSON与C++数据的双向转换。实际开发中,最常用的是objectValue(JSON对象)和arrayValue(JSON数组)的嵌套组合,需重点掌握Json::Value的赋值、访问、遍历方法,以及解析/序列化的基本流程。