c++ boost::json

这篇具有很好参考价值的文章主要介绍了c++ boost::json。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Boost社区12月11日发布了1.75版本,在之前,​​Boost使用Boost.PropertyTree解析​​JSON​​​,​​XML​​​,​​INI​​​和​​INFO​​​格式的文件。但是由于成文较早及需要兼容其他的数据格式,相比较于其他的​​C++​​解析库,使用时不方便。

​Boost.JSON​​​相对于​​Boost.PropertyTree​​​来所,其只能支持​​JSON​​格式的解析,但是其使用方法更为简便,直接。

有两种方法使用​​Boost.JSON​​​,一种是动态链接库,此时引入头文件​​boost/json.hpp​​​,同时链接对应的动态库;第二种是使用header only模式,此时只需要引入头文件​​boost/json/src.hpp​​即可。

​数据类型

array

数组类型,用于储存​​JSON​​​中的数组。实际使用的时候类似于​​std::vectorboost::json::value​​,差异极小。

object

object是JSON键值对的容器,对象类型,用于储存​​JSON​​​中的对象。实际使用时类似于​​std::map<std::string, boost::json::value>​​,但是相对来说,它们之间的差异较大。定义在<boost/json/object.hpp>

项目 Value
at(key) 获取指定Key对应的元素的引用(不存在时会抛出out_of_range异常)
begin/end 获取iterator
capacity 容量
cbegin/cend 获取const iterator
clear Erase all elements.
contains(key) 判断Key是否存在
count(key) 返回Key的数量
emplace Construct an element in-place.
empty 是否为空
erase(it/key) 根据key或iterator移除元素
find(key) 返回指定key的iterator或end()。
if_contains(key) 返回key对应value的指针,或null(不存在时)。
insert 插入元素
insert_or_assign 插入或赋值(若key已存在)
operator= Copy assignment.Move assignment.Assignment.
operator[] 存在返回对应引用,若不存在则插入null value,并返回
reserve 增加容量(若指定值小于现有容量,则什么也不做)
size 大小
swap Swap two objects.
max_size 静态成员,返回object能保存元素的最大数量。

string

字符串类型,用于储存​​JSON​​​中的字符串。实际使用时和​​std::basic_string​​​类似,不过其只支持​​UTF-8​​编码,如果需要支持其他编码,在解码时候需要修改option中相应的选项。

value

表示JSON值的类型,可以储存任意类型,也可以变换为各种类型。其中有一些特色的函数比如​​as_object​​​,​​get_array​​​,​​emplace_int64​​​之类的。它们的工作都类似,将​​boost::json::value​​对象转化为对应的类型。但是他们之间也有一定的区别。

构造json

{
    "a_string" : "test_string",
    "a_number" : 123,
    "a_null"   : null,
    "a_array"  : [1, "2", {"123" : "123"}],
    "a_object" : {
        "a_name": "a_data"
    },
    "a_bool"   : true
}

构造的方法也很简单:定义一个object,然后设定各个value即可

boost::json::object val;
val["a_string"] = "test_string";
val["a_number"] = 123;
val["a_null"] = nullptr;
val["a_array"] = {
    1, "2", boost::json::object({{"123", "123"}})
};
val["a_object"].emplace_object()["a_name"] = "a_data";
val["a_bool"] = true;

Boost.JSON​​​支持使用​​std::initializer_list​​来构造自己的对象。所以也可以这样使用:

boost::json::value val2 = {
    {"a_string", "test_string"},
    {"a_number", 123},
    {"a_null", nullptr},
    {"a_array", {1, "2", {{"123", "123"}}}},
    {"a_object", {{"a_name", "a_data"}}},
    {"a_bool", true}
};

但是使用initializer_list构造时,有时很难区分是数组还是对象,可以明确指定

// 构造[["data", "value"]]
boost::json::value jsonAry = {boost::json::array({"data", "value"})};

// 构造{"data": "value"}
boost::json::value jsonObj = boost::json::object({{"data", "value"}});

序列化

生成了​​json​​​对象以后,就可以使用​​serialize​​对对象进行序列化了。

std::cout << boost::json::serialize(val2) << std::endl;

除了直接把整个对象直接输出,​​Boost.JSON​​还支持分部分进行流输出,这种方法在数据量较大时,可以有效降低内存占用。

boost::json::serializer ser;
ser.reset(&val);

char temp_buff[6];
while (!ser.done()) {
    std::memset(temp_buff, 0, sizeof(char) * 6);
    ser.read(temp_buff, 5);
    std::cout << temp_buff << std::endl;
}

如果缓存变量是数组,还可以直接使用​​ser.read(temp_buff)​​。

需要注意的是,​​ser.read​​​并不会默认在字符串末尾加​​\0​​​,所以如果需要直接输出,在输入时对缓存置0,同时为​​\0​​空余一个字符。

也可以直接使用输出的​​boost::string_view​​。

对象序列化

对象转换为JSON,Boost.JSON提供了一个非常简单的方法:只需要在需要序列化的类的命名空间中,定义一个重载函数tag_invoke(是类所在的命名空间,而不是在类里面定义),然后通过value_from即可方便地序列化对象了:

namespace NSJsonTest {
	class MyClass {
	public:
		int a;
		int b;
		MyClass (int a = 0, int b = 1):
		a(a), b(b) {}
	};

	void tag_invoke(boost::json::value_from_tag, boost::json::value &jv, MyClass const &c) {
		auto & jo = jv.emplace_object();
		jo["a"] = c.a;
		jo["b"] = c.b;
	}
	
	MyClass myObj;
	auto jv = boost::json::value_from(myObj)
}

其中,​​boost::json::value_from_tag​​​是作为标签存在的,方便​​Boost.JSON​​​分辨序列化函数的。​​jv​​​是输出的​​JSON​​​对象,​​c​​是输入的对象。

boost::json::value_from(MyObj)

使用的话,直接调用​​value_from​​函数即可。
序列化还有一个好处就是,可以在使用​​std::initializer_list​​​初始化​​JSON​​对象时,直接使用自定义对象。譬如:

boost::json::value val = {MyObj};

这里的​​val​​​是一个数组,里面包含了一个对象​​MyObj​​。

反序列化

使用​​boost::json::parse​​

auto decode_val = boost::json::parse("{\"123\": [1, 2, 3]}");

增加错误处理

boost::json::error_code ec;
boost::json::parse("{\"123\": [1, 2, 3]}", ec);
std::cout << ec.message() << std::endl;

boost::json::parse("{\"123\": [1, 2, 3}", ec);
std::cout << ec.message() << std::endl;

对象反序列化

与对象序列化对应的是对象反序列化;也是在命名空间中定义个tag_invoke函数,然后即可通过value_to把JSON对象反序列化为类对象了:

MyClass tag_invoke(boost::json::value_to_tag<MyClass>, boost::json::value const &jv) {
	auto &jo = jv.as_object();
	return MyClass(jo.at("a").as_int64(), jo.at("b").as_int64());
}

// jv为前面序列化时的对象
auto myObj = boost::json::value_to<MyClass>(jv);

需要注意的是,由于传入的​​jv​​​是被​​const​​​修饰的,所以不能类似于​​jv[“a”]​​使用。

使用也和上面的类似,提供了一个​​value_to<>​​模板函数。

auto MyObj = boost::json::value_to<MyNameSpace::MyClass>(vj);

无论是序列化还是反序列化,对于标准库中的容器,​​Boost.JSON​​都可以直接使用。

流输入

通过stream_parser可以流的方式读入要解析的字符串

boost::json::stream_parser p;
p.reset();

p.write("[1, 2,");
p.write("3]");
p.finish();

std::cout << boost::json::serialize(p.release()) << std::endl;

示例

json文件:
c++ boost::json,c++,c++,json,开发语言

#include <boost/json.hpp>
#include <boost/json/src.hpp>
#include <iostream>
#include <iterator>
#include <fstream>
namespace json = boost::json;

struct Rec {
    int64_t number;
    std::string string;

    friend Rec tag_invoke(json::value_to_tag<Rec>, json::value const& v) {
        auto& o = v.as_object();
        return {
                o.at("number").as_int64(),
                boost::json::value_to<std::string>(o.at("string")),
        };
    }

    friend void tag_invoke(json::value_from_tag, json::value& v, Rec const& rec)
    {
        v = json::object{
                {"number", rec.number},
                {"string", rec.string},
        };
    }
};

int main() {
    std::ifstream ifs("../input.json");
    std::string   input(std::istreambuf_iterator<char>(ifs), {});

    using Recs = std::vector<Rec>;
    Recs recs  = boost::json::value_to<std::vector<Rec>>(json::parse(input));

    for (auto& [n, s] : recs) {
        std::cout << "Rec { " << n << ", " << std::quoted(s) << " }\n";

        // some frivolous changes:
        n *= 2;
        reverse(begin(s), end(s));
    }

    std::cout << "Modified json: " << json::value_from(recs) << "\n";
}

参考
Boost.JSON Boost的JSON解析库文章来源地址https://www.toymoban.com/news/detail-681723.html

到了这里,关于c++ boost::json的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++】开源:Boost库常用组件配置使用

    😏 ★,° :.☆( ̄▽ ̄)/$: .°★ 😏 这篇文章主要介绍Boost库常用组件配置使用。 无专精则不能成,无涉猎则不能通。——梁启超 欢迎来到我的博客,一起学习,共同进步。 喜欢的朋友可以关注一下,下次更新不迷路🥞 项目Github地址: https://github.com/boostorg/boost Boost库在线书籍

    2024年02月15日
    浏览(56)
  • 【C++】开源:Boost网络库Asio配置使用

    😏 ★,° :.☆( ̄▽ ̄)/$: .°★ 😏 这篇文章主要介绍Asio网络库配置使用。 无专精则不能成,无涉猎则不能通。——梁启超 欢迎来到我的博客,一起学习,共同进步。 喜欢的朋友可以关注一下,下次更新不迷路🥞 项目Github地址: https://github.com/boostorg/asio Boost.Asio 是一个用于

    2024年02月15日
    浏览(48)
  • C++使用boost::serialization进行序列化

    发现一个比较好玩的东西,boost::serialization序列化操作,简单来说感觉像ofstream和ifstream的升级版,Boost.Serialization 库能够将c++项目中的对象转换为一序列的比特(bytes),用来保存和加载还原对象。 在ORBSLAM3保存和加载地图的时候好像就是采用的这种方法,后面需要再深入研究

    2024年02月08日
    浏览(45)
  • 源自Boost最优雅的C++单例模式

    Boost功能非常强大,在此借鉴一下其线程库中的单例源码,线程安全且优雅。 include/boost/thread/detail/singleton.hpp

    2024年02月17日
    浏览(33)
  • 【程序员必备】UE4 C++ 虚幻引擎:详解JSON文件读、写、解析,打造高效开发!

    🙋‍♂️ 作者:海码007 📜 专栏:UE虚幻引擎专栏 💥 标题:【程序员必备】UE4 C++ 虚幻引擎:详解JSON文件读、写、解析,打造高效开发! ❣️ 寄语:人生的意义或许可以发挥自己全部的潜力,所以加油吧! 🎈 最后: 文章作者技术和水平有限,如果文中出现错误,希望大

    2024年02月03日
    浏览(57)
  • (自己动手开发自己的语言练手级应用)JSON(JavaScript Object Notation) 产生式(BNF)

     写自己的开发语言时,很多人都会拿JSON当第一个练习对象 开源net json FJSON 解析工具 https://dbrwe.blog.csdn.net/article/details/107611540?spm=1001.2014.3001.5502 以上是JSON的简化产生式表示形式。其中, json 是最顶层的规则,可以是一个对象或一个数组。 object 表示一个对象,由一对大括号

    2024年02月10日
    浏览(53)
  • 4.4 C++ Boost 数据集序列化库

    Boost 库是一个由C/C++语言的开发者创建并更新维护的开源类库,其提供了许多功能强大的程序库和工具,用于开发高质量、可移植、高效的C应用程序。Boost库可以作为标准C库的后备,通常被称为准标准库,是C标准化进程的重要开发引擎之一。使用Boost库可以加速C应用程序的开

    2024年02月12日
    浏览(39)
  • Boost开发指南-4.3optional

    在实际的软件开发过程中我们经常会遇到“无效值”的情况,例如函数并不是总能返回有效值,很多时候函数正确执行了,但结果却不是合理的值。如果用数学语言来解释,就是返回值位于函数解空间之外。 求一个数的倒数,在实数域内开平方,在字符串中查找子串,它们都

    2024年02月13日
    浏览(40)
  • Boost开发指南-4.4assign

    许多情况下我们都需要为容器初始化或者赋值,填入大量的数据,比如初始错误代码和错误信息,或者是一些测试用的数据。在C++98中标准容器仅提供了容纳这些数据的方法,但填充的步骤却是相当地麻烦,必须重复调用insert()或者push_back()等成员函数,这正是boost.assign出现的

    2024年02月12日
    浏览(36)
  • C++实现websocket服务端客户端(基于boost,亲测可行!)

       整篇文章基本参考了https://blog.csdn.net/jianghuan0122/article/details/123528907,文章记录了如何在现有条件下实现该参考示例(参考示例存在报错,并且参考示例没有介绍环境安装,正确源码附于文末)    自身环境:ubuntu18.04+gcc7.5.0+boost1.7,3   gcc或者g++一般都有,这里主要介绍

    2024年02月11日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包