JSON 是什么?
JSON 是一种存储结构化数据的格式,源自 Javascript,现被广泛用于互联网上的数据交换。
用 JSON 来描述一个人:
{
"FirstName": "John",
"LastName": "Doe",
"Age": 43,
"Address": {
"Street": "Downing Street 10",
"City": "London",
"Country": "Great Britain"
},
"Phone numbers": [
"+44 1234567",
"+44 2345678"
]
}
上面的例子包括一个有 5 个键/值对的对象。
其中 FirstName 和 LastName 是字符串,
Age 是数字,Address 是对象,Phone numbers 是数组。
JSON 的 6 种数据类型:
bool
double
string
array
object
null
布尔值由字符串 true 或 false 表示。
字符串可以是任何有效的 unicode 字符串。
数组是一个值的列表,用 [] 表示;
对象是一个键/值对的集合,用 {} 表示;
对象中的所有键都是字符串,而且不能包含任何重复的键。
数组和对象中的条目用逗号分开。对象中的键和值之间的分隔符是冒号。
一个有效的 JSON 文档是一个数组或一个对象,所以 JSON 文档总是以方括号或大括号开始。
Qt 对 JSON 的支持
Qt 提供了一个易于使用的 C++ API 来解析、修改和保存 JSON 数据。
另外,还支持以二进制格式保存这些数据,这种格式可以直接被 mmap,所以访问速度非常快。
几个重点类
类名
作用
QJsonArray | 封装 JSON array |
QJsonDocument | 封装了如何读写 JSON 文件 |
QJsonObject | 封装 JSON Object |
QJsonValue | 封装 JSON value |
Qt JSON 实例
示例:
https://doc.qt.io/qt-5/qtcore-serialization-savegame-example.html
该示例演示了如何使用 QJsonDocument、QJsonObject 和 QJsonArray 来保存和加载游戏的人物信息。
许多游戏提供了保存功能,这样玩家在游戏中的进展可以被保存并在以后被加载。
保存游戏的过程通常包括将每个游戏对象的成员变量序列化到一个文件中。
许多格式可用于此目的,其中之一是 JSON。
如果你不希望保存的文件是可读的,或者你需要减小文件的大小。,还可以将文件序列化为二进制的 CBOR 格式,
在这个例子中,我们将演示如何将一个简单的游戏保存和加载到JSON 和二进制格式中。
源码文件:
# tree json/
json/
├── json.pro
└── savegame
├── character.cpp // 封装了游戏角色
├── character.h
├── game.cpp // 封装了游戏
├── game.h
├── level.cpp // 封装游戏关卡
├── level.h
├── main.cpp
├── savegame.pro
Character 类
// 文件 character.h
class Character
{
public:
// 构造函数
[...]
// 几个 setter 和 getter 函数
[...]
void read(const QJsonObject &json);
void write(QJsonObject &json) const;
private:
QString mName;
int mLevel;
ClassType mClassType;
};
封装了游戏角色,重点是成员函数 read() 和 write(),类的使用者通过这两个函数来将一个 Character 对象写到 JSON 文件中或者从 JSON 文件中读取 Character 对象。
Level 类的实现方式类似,这里就不再赘述了。
Game 类
// 文件:game.h
class Game
{
public:
Game();
enum SaveFormat {
Json, Binary
};
const Character &player() const;
const QList<Level> &levels() const;
void newGame();
bool loadGame(SaveFormat saveFormat);
bool saveGame(SaveFormat saveFormat) const;
void read(const QJsonObject &json);
void write(QJsonObject &json) const;
private:
Character mPlayer;
QList<Level> mLevels;
};
封装了游戏,newGame() 创建了游戏角色和游戏关卡等对象,loadGame() 和 saveGame() 则从文件中加载这些对象或者将对象保存到文件中。
重点看一下 saveGame():
// 文件:game.cpp
bool Game::saveGame(Game::SaveFormat saveFormat) const
{
QFile saveFile(saveFormat == Json
? QStringLiteral("save.json")
: QStringLiteral("save.dat"));
if (!saveFile.open(QIODevice::WriteOnly)) {
qWarning("Couldn't open save file.");
return false;
}
QJsonObject gameObject;
write(gameObject);
QJsonDocument saveDoc(gameObject);
saveFile.write(saveFormat == Json
? saveDoc.toJson()
: saveDoc.toBinaryData());
return true;
}
参数 saveFormat 用于指定是保存为可读的 JSON 文件还是不可读的二进制文件。
QJsonObject gameObject;
write(gameObject);
创建 QJsonObject 对象,并将游戏角色对象、游戏关卡对象等全部信息写到其中。
QJsonDocument saveDoc(gameObject);
saveFile.write(saveFormat == Json
? saveDoc.toJson()
: saveDoc.toBinaryData());
基于QJsonObject 对象,创建 QJsonDocument 对象,并使用 QFile::write() 就可以将 JSON 对象写到 JSON 文件中了。
loadGame() 从 JSON 文件中读取游戏信息的操作和 saveGame() 相反,这里也不再赘述。
main():
// 文件 main.cpp
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
Game game;
game.newGame();
if (!game.saveGame(Game::Json))
return 1;
if (!game.saveGame(Game::Binary))
return 1;
Game fromJsonGame;
if (!fromJsonGame.loadGame(Game::Json))
return 1;
Game fromBinaryGame;
if (!fromBinaryGame.loadGame(Game::Binary))
return 1;
return 0;
}
运行效果:
运行该程序后,没有效果,就是生成 2 个文件:
save.dat
save.json
save.json:
{
"levels": [
{
"npcs": [
{
"classType": 0,
"level": 10,
"name": "Barry the Blacksmith"
},
{
"classType": 0,
"level": 10,
"name": "Terry the Trader"
}
]
},
...
],
"player": {
"classType": 2,
"level": 15,
"name": "Hero"
}
}
这些数据都是在 newGame() 里 new 出来的,然后通过 saveGame() 保存下来的。
到此,Qt JSON 相关的小知识就分享完毕了。
感谢阅读~~~
—— The End ——
推荐阅读: