今天下午,和群友讨论了一下 JSON | Qt 小知识

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 ——

推荐阅读:

专辑 | Linux 驱动开发

专辑 | Linux 系统编程

专辑 | 每天一点 C

专辑 | Qt 入门

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值