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

Json快速入门

引言

Jsoncpp 库主要是用于实现 Json 格式数据的序列化和反序列化,它实现了将多个数据对象组织成 为Json格式字符串,以及将 Json 格式字符串解析得到多个数据对象的功能,独立于开发语言。

Json数据对象

Json数据对象类的表示:

class Json::Value{
 Value &operator=(const Value &other); //Value重载了[]和=,因此所有的赋值和获取数据都可以通过 
 Value& operator[](const std::string& key);//简单的⽅式完成 val["name"] = "xx";
 Value& operator[](const char* key);

 Value removeMember(const char* key);//移除元素 
 const Value& operator[](ArrayIndex index) const; //val["score"][0]
 Value& append(const Value& value);//添加数组元素val["score"].append(88);  
 ArrayIndex size() const;//获取数组元素个数 val["score"].size(); 

 std::string asString() const;//转string string name = val["name"].asString();
 const char* asCString() const;//转char* char *name = val["name"].asCString();
 Int asInt() const;//转int int age = val["age"].asInt(); 
 float asFloat() const;//转float float weight = val["weight"].asFloat(); 
 bool asBool() const;//转 bool bool ok = val["ok"].asBool(); 
};

上面列举了Json数据对象Json::Value的一些成员方法, Json::Value是用来存储数据的,可以把它理解为一个容器。序列化方法和反序列化方法就可以将传入的Json::Value数据对象进行序列化和反序列化操作。

Json基本语法规则

Json通常采用KeyValue的格式。例如:“姓名”:“小颖”,中间用冒号:隔开。其中,键名必须为字符串且必须用双引号包裹。

{ "key": "value" }  // ✅ 正确
{ key: "value" }    // ❌ 错误

Json中还有另一种数据结构——数组。用中括号[ ]包裹起来,里面的值的类型可以不同。

 ["苹果", "香蕉", 123, true]

序列化接口

class JSON_API StreamWriter {
 virtual int write(Value const& root, std::ostream* sout) = 0;
 //......
}
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
 virtual StreamWriter* newStreamWriter() const;
  //......
}

可以看得出来,这里用到了一种设计模式——工厂模式。 也就是说使用StreamWriterBuilder 来生产StreamWriter对象。write就是序列化接口,第一个参数为存储数据的Value对象,第二个参数为输出流对象的指针。StreamWriter用于将JSON数据写入到输出流中,StreamWriterBuilder则是用来配置和创建StreamWriter实例的。所谓配置,就是配置Json输出的格式,比如缩进、换行这些都是。下面用代码演示如何对数据进行序列化。

反序列化接口

class JSON_API CharReader {
 virtual bool parse(char const* beginDoc, char const* endDoc, 
 Value* root, std::string* errs) = 0;
}
class JSON_API CharReaderBuilder : public CharReader::Factory {
 virtual CharReader* newCharReader() const;
}

和序列化一样,这里同样用到了工厂设计模式。CharReaderBuilder 负责配置解析规则,然后由CharReader来进行解析。CharReader不能直接创建对象,因为它里面有个纯虚函数,所以它是个抽象类。创建对象的职责由CharReaderBuilder来承担。函数parse就是用来完成反序列化的。

序列化和反序列化代码演示

#include <iostream>
#include <memory>
#include <sstream>
#include <jsoncpp/json/json.h>

//序列化
bool Serialize(const Json::Value val, std::string &body)
{
    std::stringstream ss;
    //构建StreamWriter对象
    Json::StreamWriterBuilder swb;
    std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
    int ret = sw->write(val, &ss);//成功返回0,失败返回-1
    if(ret != 0)
    {
        std::cout << "serialize faild\n";
        return false;
    }
    body = ss.str();
    return true;
}

//反序列化
bool unserialize(const std::string &body, Json::Value&val)
{
    Json::CharReaderBuilder crb;
    std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
    std::string errs;
    bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val, &errs);
    if(ret == false)
    {
        std::cout << "unserialize faild : " << errs << std::endl;
        return false;
    }
    return true;
}

int main()
{
    Json::Value stu;
    stu["姓名"] = "小颖";
    stu["年龄"] = 19;
    //构建数组,不能直接stu["爱好"] = ["打羽毛球", "吃吃吃", "散步"];
    stu["爱好"].append("打羽毛球");
    stu["爱好"].append("吃吃吃");
    stu["爱好"].append("散步");

    std::string body;
    Serialize(stu, body);
    std::cout << body << std::endl;

    std::string str = R"({"姓名":"小北", "年龄":20})";//C++11的一种新语法,定义一个字符串
    Json::Value student;
    bool ret = unserialize(str, student);//将字符串反序列化
    if(ret == false)
        return -1;
    std::cout << "姓名:" << student["姓名"].asString() << std::endl;
    std::cout << "年龄:" << student["年龄"].asInt() << std::endl;

    return 0;
}

//运行结果
{
        "\u59d3\u540d" : "\u5c0f\u9896",
        "\u5e74\u9f84" : 19,
        "\u7231\u597d" : 
        [
                "\u6253\u7fbd\u6bdb\u7403",
                "\u5403\u5403\u5403",
                "\u6563\u6b65"
        ]
}
姓名:小北
年龄:20

相关文章:

  • C++中的move操作
  • python 判断字符串是否包含关键字
  • 7.2 重复推送(每日、每周等)
  • springboot集成kafka,后续需要通过flask封装restful接口
  • 基于 Node.js 和 Spring Boot 的 RSA 加密登录实践
  • 程序化广告行业(70/89):ABTester系统助力落地页优化实践
  • 【C++篇】深入解析C/C++内存管理:从原理到实践
  • c语言 文件操作
  • MTO和MTS不同模式制造业数字化转型的“三座大山“:MES/ERP/PLM系统集成技术全解析
  • Buffer Pool 的核心作用与工作机制
  • uni-app使用web-view传参的坑
  • HOW - React Error Catch 机制
  • Three.js 系列专题 7:性能优化与最佳实践
  • TVBOX最新配置接口\直播源接口 收集整理【 2025.4】
  • Token无感刷新
  • 蓝桥杯备赛 Day 21 图论基础
  • 拼多多商品详情接口爬虫实战指南
  • 多线程代码案例(线程池)- 4
  • Rust 之四 运算符、标量、元组、数组、字符串、结构体、枚举
  • springboot Filter实现请求响应全链路拦截!完整日志监控方案​​
  • 杭勇已任常州市政协党组成员,此前任常州市委常委、秘书长
  • 高波︱忆陈昊:在中年之前离去
  • 盖茨说对中国技术封锁起到反作用
  • 再获殊荣!IP SH跻身上海文化品牌全球传播力TOP 6
  • 百利天恒董事长向复旦捐赠三千万元,用于支持创新药物靶点发现等师资建设需要
  • 黄土是他们的气质:打破宁夏当代油画创作的沉寂