C++对象Json序列化最佳实践(基于Rapidjson库):C++内存对象和Json字符串互相转换

c++ 使用rapidjson对数据序列化和反序列化(vs2109) c++ 使用rapidjson对数据序列化和反序列化,json序列化和反序列化 阅读详情

介绍:Rapidjson

Rapidjson库是C++对象序列化到Json字符串的非常好的工具,以效率著称,腾讯的人写的。

官方网站:点击打开链接

本文全部资源百度云

这个库的缺点(个人拙见):

1 暴露的细节相对较多:容器,迭代器,类型,成员函数,序列化,反序列化,都有非常细致的操作。这个给使用者带来记忆负担较重。至少需要同时暴露Value类型和Document类型才能完整的实现Object内部包含Object类型。但这个包装起来很麻烦。

2 使用移动语义和自动内存回收:这个是内存占用小的保障,但是光是移动语义就给使用者造成很多不便。移动语义当然提高了效率,但是和使用者的程序代码风格不能很好的融合。移动语义使得Document的管理的内存数据在Document释放的时候就被析构,Object内包含Object的时候不好像C++基础类型语义那样去赋值操作(赋值就是副本,不担心原对象释放)。为了既能够使用移动语义和Document自动管理内存,又能够使用子对象的数据赋值,本文实现的CJsonObject对象返回和设置子对象均使用std::shared_ptr<CJsonObject>来实现。

3 序列化的思路好,但是没有和反序列化很好的结合:

官网上的序列化实现的思路是仿照STL的思路,使用类似输出操作符重载的方式给类增加序列化的函数(而不是输出操作符重载),从而使得复杂的类型(包括类类型成员的)可以借助成员类型的序列化来实现自己的序列化。

这种方式好处是明显的,程序结构清晰,Rapidjson对现有代码的冲击最小,想序列化哪一个就实现个序列化的成员函数就行了。但是却没有发现反序列化的例子。反序列化就是将json字符串通过Parse来创建一个C++内存对象,从而使用这个内存对象。

其实和序列化的场景一样,大多数人使用json都是想让原有类型支持序列化和反序列化,而不是抛弃原有类型(原有类型存在于大量的已有代码中,这样冲击太大)

还有一种思路是:将Rapidjson视为反序列化的工具,需要反序列化的时候临时创建Document对象来实现。但是数据在Document中,要想让现有C++类拿到这些数据,还是要一个一个的GetInt,GetBool,GetDouble等取出来再赋值给现有C++对象。这个是无法忍受的,只能再实现一套帮助类来做转换。这样增加了一批帮助类其实也是负担,而且程序代码分散而不集中。


本文的思路:

1 借鉴Rapidjson序列化的思路,让需要序列化的类自己实现统一的(通过实现基类CJsonBase来做到)序列化和反序列化成员函数。这样对现有代码的冲击最小,需要新写的代码量最小,最大程度的保护的原有的C++业务类

2 为序列化和反序列化实现一个执行类:CJsonObject,该类型提供序列化和反序列化时的所有操作实现。包括:CreateFromJson,ToJson,Get/SetInt GetSetBool 等。

3 优点:对现有代码的冲击最小(只需要包含添加CJsonObject类即可);只针对对现有代码的序列化和反序列化场景(比如C++对象存储到Redis;公开接口API形式跟外部通信,等等)

本文示例代码:借鉴了官网的serialize.cpp实现

#include "stdafx.h"
#include "JsonObject.h"
#include "Person.h"

#include <iostream>
#include <list>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	std::list<Employee> employees;
	std::list<Employee> employeesCopyFromJson;

	employees.push_back(Employee("Milo YIP", 34, true));
	employees.back().AddDependent(Dependent("Lua YIP", 3, new Education("Happy Kindergarten", 3.5)));
	employees.back().AddDependent(Dependent("Mio YIP", 1));
	
	employees.push_back(Employee("Percy TSE", 30, false));

	cout<<"C++对象->Json字符串:"<<endl;
	for (auto itr = employees.begin(); itr != employees.end(); ++itr)
	{
		cout<< itr->ToJson()<<endl;
		Employee employee;
		employee.CreateFromJson(itr->ToJson().c_str());
		employeesCopyFromJson.push_back(employee);
	}
	cout<<endl;
	cout<<"Json字符串->C++对象->Json字符串:"<<endl;

	for (auto itr = employeesCopyFromJson.begin(); itr != employeesCopyFromJson.end(); ++itr)
	{
		cout<< itr->ToJson()<<endl;
	}

	 return 0;
}


程序输出:

C++对象->Json字符串:
{
    "name": "Milo YIP",
    "age": 34,
    "dependent": [
        {
            "name": "Lua YIP",
            "age": 3,
            "education": {
                "school": "Happy Kindergarten",
                "GPA": 3.5
            }
        },
        {
            "name": "Mio YIP",
            "age": 1
        }
    ],
    "married": true
}
{
    "name": "Percy TSE",
    "age": 30,
    "dependent": [],
    "married": false
}

Json字符串->C++对象->Json字符串:
{
    "name": "Milo YIP",
    "age": 34,
    "dependent": [
        {
            "name": "Lua YIP",
            "age": 3,
            "education": {
                "school": "Happy Kindergarten",
                "GPA": 3.5
            }
        },
        {
            "name": "Mio YIP",
            "age": 1
        }
    ],
    "married": true
}
{
    "name": "Percy TSE",
    "age": 30,
    "dependent": [],
    "married": false
}
请按任意键继续. . .

附件:本文修改官网序列化示例代码的Person.h文件

#include <list>
#include <memory>
#include <vector>
#include "JsonObject.h"

class Person : public CJsonObjectBase
{
public:
	Person(void){}
	Person(const std::string& name, unsigned age) : name_(name), age_(age) {}
	Person(const Person& rhs) : name_(rhs.name_), age_(rhs.age_) {}
	virtual ~Person();
	//序列化
	virtual std::string ToJson(void) const
	{
		CJsonObject json;
		json.SetStringValue("name", name_);
		json.SetULongValue("age", age_);

		return json.ToJson();
	}
	//反序列化
	virtual void CreateFromJson(const char* _json)
	{
		CJsonObject jsonObj;
		jsonObj.CreateFromJson(_json);
		name_ = jsonObj.GetStringValue("name");
		age_ = jsonObj.GetULongValue("age");
	}


	Person& operator=(const Person& rhs) {
		name_ = rhs.name_;
		age_ = rhs.age_;
		return *this;
	}

public:
	std::string name_;
	unsigned age_;
};

Person::~Person() {
}

class Education  : public CJsonObjectBase{
public:
	Education(void) {}
	Education(const std::string& school, double GPA) : school_(school), GPA_(GPA) {}
	Education(const Education& rhs) : school_(rhs.school_), GPA_(rhs.GPA_) {}
	//序列化
	virtual std::string ToJson(void) const
	{
		CJsonObject json;
		json.SetStringValue("school", school_);
		json.SetDoubleValue("GPA", GPA_);
		return json.ToJson();
	}
	//反序列化
	virtual void CreateFromJson(const char* _json)
	{
		CJsonObject jsonObj;
		jsonObj.CreateFromJson(_json);
		school_ = jsonObj.GetStringValue("school");
		GPA_ = jsonObj.GetDoubleValue("GPA");
	}

public:
	std::string school_;
	double GPA_;
};

class Dependent : public Person {
public:
	Dependent(void):education_(0){};
	Dependent(const std::string& name, unsigned age, Education* education = 0) : Person(name, age), education_(education) {}
	Dependent(const Dependent& rhs) : Person(rhs), education_(0) { education_ = (rhs.education_ == 0) ? 0 : new Education(*rhs.education_); }
	virtual ~Dependent();

	Dependent& operator=(const Dependent& rhs) {
		if (this == &rhs)
			return *this;
		delete education_;
		education_ = (rhs.education_ == 0) ? 0 : new Education(*rhs.education_);
		return *this;
	}

	//序列化
	virtual std::string ToJson(void) const
	{
		CJsonObject json;
		json.CreateFromJson(Person::ToJson().c_str());
		
		std::shared_ptr<CJsonObject> spEducationObj = std::make_shared<CJsonObject>();
		if (education_ != nullptr)
		{
			spEducationObj->CreateFromJson(education_->ToJson().c_str());
			json.SetObjectValue("education", spEducationObj);
		}
		else
		{
			//空指针的话,Json中根本就没这个成员
		}

		return json.ToJson();
	}
	//反序列化
	virtual void CreateFromJson(const char* _json)
	{
		Person::CreateFromJson(_json);

		CJsonObject jsonObj;
		jsonObj.CreateFromJson(_json);

		if (education_ != nullptr)
		{
			delete education_;
			education_ = nullptr;
		}
		try
		{
			auto spEdution = jsonObj.GetObjectValue("education");
			education_ = new Education;
			education_->CreateFromJson(spEdution->ToJson().c_str());
		}
		catch (CJsonException e)
		{
			delete education_;
			education_ = nullptr;
		}
	}

public:
	Education *education_;
};

Dependent::~Dependent() {
	delete education_; 
}

class Employee : public Person {
public:
	Employee(void){};
	Employee(const std::string& name, unsigned age, bool married) : Person(name, age), dependents_(), married_(married) {}
	Employee(const Employee& rhs) : Person(rhs), dependents_(rhs.dependents_), married_(rhs.married_) {}
	virtual ~Employee();

	//序列化
	virtual std::string ToJson(void) const;
	//反序列化
	virtual void CreateFromJson(const char* _json);

	Employee& operator=(const Employee& rhs) {
		static_cast<Person&>(*this) = rhs;
		dependents_ = rhs.dependents_;
		married_ = rhs.married_;
		return *this;
	}

	void AddDependent(const Dependent& dependent) {
		dependents_.push_back(dependent);
	}

public:
	std::vector<Dependent> dependents_;
	bool married_;
};

Employee::~Employee() {
}

std::string Employee::ToJson(void) const
{
	std::list<std::shared_ptr<CJsonObject>> listJsonObj;
	for (auto itr = dependents_.begin(); itr != dependents_.end(); ++itr)
	{
		std::shared_ptr<CJsonObject> pJsonDependent = std::make_shared<CJsonObject>();
		pJsonDependent->CreateFromJson(itr->ToJson());
		listJsonObj.push_back(pJsonDependent);
		//listJsonObj.push_back(CJsonObject);//这种写法:复制到容器的副本会导致原来的对象析构
	}

	CJsonObject json;
	json.CreateFromJson(Person::ToJson());
	json.SetObjectListValue("dependent", listJsonObj);
	json.SetBoolValue("married", married_);
	
	std::string str = json.ToJson();
	
	return std::move(str);
}

void Employee::CreateFromJson(const char* _json)
{
	Person::CreateFromJson(_json);

	CJsonObject jsonObj;
	jsonObj.CreateFromJson(_json);

	married_ = jsonObj.GetBoolValue("married");

	auto listDependents = jsonObj.GetObjectListValue("dependent");
	

	for (auto itr = listDependents.begin(); itr != listDependents.end(); ++itr)
	{
		Dependent dependent;
		dependent.CreateFromJson((*itr)->ToJson().c_str());
		this->dependents_.push_back(dependent);
	}
}

全部资源:

有需要的联系我头像

有需要的扫描我头像加我即可。(付费资源哦!)



C++中json解析开源库收集,支持json5 ZPL库 是一个多功能集合库,其中有 JSON5 解析器。支持注释 链接: https://github.com/zpl-c/zpl# HJSON HJSON支持注释,支持多种语言。 链接:https://github.com/hjson/ cJSON 用c写的超轻量级JSON解析器。只有一个.h和.c。 链接:https://github.com/DaveGamble/cJSON ... 阅读详情

相关推荐

Python3 JSON库json、orjson、rapidjson loads和dumps速度对比

项目中需要将json字符串反序列化成Python字典对象,但发现原生的json库速度非常慢,就想使用第三方库取代它,发现了orjson和rapidjson两个比较流行的第三方库,测试一下 环境 Python 3.8.6 macOS 11.1 orjson 3.4.6 rapidjson 1.0 介绍 orjson Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy 号称Python下最快的jso

MacwinWin的博客 3256

C++对象与Json对象的完美转换

c++ qt通过宏函数方式将代码入侵至struct/class内,完成json与对象的相互转换。

weixin_43942000的博客 455

C++与RapidJSON解析JSON数据实战指南

在信息技术领域,JSON(JavaScript Object Notation)已成为一种广泛使用的数据交换格式。JSON以其轻量级、可读性强以及易于人机解析的特点,被大量用于网络通信协议以及Web服务中。JSON数据由键值对组成,能够有效地表示结构化数据,支持数组、对象、字符串、数字、布尔值和null这几种数据类型。在C++中应用JSON数据,可以借助诸如RapidJSON、nlohmann/json等专门的库来实现。

weixin_32445049的博客 807

基于RapidJson的c++类的序列化和反序列化

目录 一、rapidjson简介 二、序列化思路 三、C++实体类的的序列化和反序列化 1、RapidjsonHelper帮助类 2、实体类的的序列化和反序列化 3、main函数 四、下载 一、rapidjson简介 RapidJSON 是一个 C++ 的 JSON 解析器及生成器。它的灵感来自RapidXml。 RapidJSON 小而全。它同时支持 SAX 和 DOM 风格的 API。SAX 解析器只有约 500 行代码。 RapidJSON 快。它的性...

kupePoem的专栏 3601

Lua与RapidJSON的深入集成:实现高效JSON处理

本文还有配套的精品资源,点击获取 简介:本文介绍了lua-rapidjson-master项目,它将RapidJSON的高效解析和生成功能与Lua语言紧密结合,通过简单的API实现了在Lua中直接处理JSON数据。该项目支持JSON的序列化与反序列化,并利用Lua的元表机制,使JSON对象能够像操作Lua表格一样进行访问。它还提供了JSON Schema验证功能,增强了数据...

weixin_42577243的博客 1226

C++ rapidjson 对类序列化(完美二次封装)下载

本工程源码,基于rapidjson实现二次封装,使C++序列化一个类的变得代码非常小,耦合性非常低,且不损失原有序列化性能。详细使用可关联本人博客:http://blog.youkuaiyun.com/lightspear/article/details/54836656

C++ 两行代码实现json与类对象互转

背景与需求 之前写C#的时候,解析json字符串一般使用的是开源的类库Newtonsoft.Json,方法十分简洁,比如: class Project { public string Input { get; set; } public string Output { get; set; } } JavaScriptSerializer serializer = new JavaScriptSerializer(); Project test = serializer.Deserialize

Yaronzz 7070

C++ [ rapidjson 使用、封装、UT]、[Base64加码及解码]

C++ [ rapidjson 使用、封装、UT]、[Base64加码及解码]

rapidjson序列化:C++对象到JSON的转换实现

在C++开发中,JSON(JavaScript Object Notation)数据交换格式已成为事实标准。然而,传统的JSON库往往面临性能瓶颈、内存占用高、API复杂等问题。当你的应用需要处理大量JSON数据时,一个高效的序列化方案至关重要。 rapidjson作为腾讯开源的C++ JSON解析/生成库,以其卓越的性能和简洁的API设计,成为解决这一痛点的理想选择。本文将深入探讨rapidj...

gitblog_00104的博客 981

告别Godot默认编辑器:手把手教你用VSCode配置C#开发环境(附中文注释避坑指南)

本文详细介绍了如何将VSCode配置为Godot引擎的C#开发环境,提升游戏开发效率。从环境准备、扩展配置到解决中文编码问题,提供完整的避坑指南和高级调试技巧,帮助开发者充分利用VSCode的智能补全和调试功能,打造高效工作流。

weixin_30596023的博客 189

core_analyzer分析c++程序内存占用

环境:centos; 进程:单进程多线程c++程序; 问题:1. 分析系统内存占用; 2. 分析ptmalloc内存空洞(bins上的空闲chunk的大小); 包括:1. 占用了很大内存的c++进程; 2. gcore(在进程不core dump的情况下生成core文件); 3. core_analyzer(分析gcor...

weixin_41644391的博客 4812

【C/C++】C++Json解析和生成的开源库:RapidJson和JsonCpp

RapidJson和JsonCpp都是C++中流行的JSON解析器和生成器,并且都是开源库,具有许多相似的功能,但也有不同之处,具体使用都有所介绍,并写有例子来加深理解!

weixin_43729127的博客 4252

PCB激光直接成像(LDI)设备技术解析与优化方案

激光直接成像(LDI)是PCB制造中的关键数字化工艺,通过激光束直接在基板上形成电路图案。其核心技术在于高精度光学系统与智能控制算法的结合,工作精度可达微米级。在HDI板、柔性电路等高端PCB制造中,LDI技术能显著提升线宽精度和层间对位准确性。当前行业面临材料适配性、热变形控制等挑战,动态能量补偿、多波长曝光等创新方案正在突破这些瓶颈。随着模块化设计、预测性维护等工程实践的普及,LDI设备综合效率持续提升,为5G、汽车电子等领域的精密电路生产提供关键技术支撑。

weixin_29168393的博客 393

[C++]JSON RAPIDJSON及JSONCPP的对比使用

不同的语言中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。jsoncpp是c++解析JSON串常用的解析库之一,它是一个序列化反序列JSON格式的开源C++库,被C++程序广泛使用(包括Chromium项目)。RapidJSON是腾讯开源的一个高效的C++ JSON解析器及生成器,它是只有头文件的C++库。

FL1768317420的博客 1471

深入RK3588嵌入式Linux开发:uboot源码定制化移植实战

本文详细介绍了RK3588嵌入式Linux开发中,如何绕过庞大的官方SDK,从官方仓库获取纯净U-Boot源码并进行定制化移植的完整实战流程。内容包括编译环境搭建、交叉工具链配置、源码结构解析、设备树(Device Tree)修改、环境变量定制、编译脚本编写以及常见问题调试技巧,旨在帮助开发者深入理解系统引导过程,掌握为定制硬件适配U-Boot的核心技能。

weixin_29169505的博客 423

Mac 不小心断开移动硬盘导致磁盘无法读取和加载(顺利解决!)

Mac移动硬盘不正确断开连接导致无法读取加载的解决方法,亲测有效

Robin_Pi的博客 1万+

开源 C++ JSON 库 sonic-cpp解析性能为 rapidjson 的 2.5 倍

sonic-cpp 是由字节跳动 STE 团队和服务框架团队共同研发的一款面向 C++ 语言的高效 JSON 库,极致地利用当前 CPU 硬件特性与向量化编程,大幅提高了序列化反序列化性能,解析性能为 rapidjson 的 2.5 倍。 sonic-cpp 在字节内部上线以来, 已为抖音、今日头条等核心业务,累计节省了数十万 CPU 核心。近日,我们正式对外开源 sonic-cpp,希望能够帮助更多开发者,欢迎大家 star、fork。Github:https://github.com/bytedance

u012181546的博客 3004

comfyui从入门到精通二:提示词规则详解

《AI绘画提示词使用全指南》摘要: 本文系统解析AI绘画提示词的核心规则与实用技巧。关键点包括:1) 空格与下划线的本质差异,webui会自动转换但comfyui保留原格式;2) 数字与单词表达(如1girl/one girl)会导致风格变化;3) 三种权重控制方式(数值标注、括号嵌套、位置效应),其中数值标注最直观有效;4) 位置衰减公式揭示提示词排序对效果的影响权重。同时指出当前AI绘画仍存在角色一致性等更复杂的技术瓶颈。全文通过多组对比实验,为创作者提供从基础语法到高阶控制的完整解决方案。

ScottePerk的博客 1934

使用RapidJson开源库解析和生成Json数据

RapidJSON是一个高效、轻量级的 C++ JSON 解析器及生成器库,由腾讯公司开源。 RapidJSON 是只有头文件的 C++ 库。只需把 include/rapidjson 目录复制到项目中即可使用。

new9232的博客 2045

2026从0到1!C#工控机开发实战指南:新手一周就能跑通的完整项目

这篇文章摘要如下: 工业自动化领域工控机开发入门指南,针对零基础开发者提供从环境搭建到项目实战的全流程指导。文章首先解答工控机开发的3个核心问题,比较工控机与普通PC的区别,推荐使用C#作为开发语言。随后详细讲解开发环境配置、四大核心技术栈(通信协议、数据库、UI框架、多线程),并重点演示Modbus TCP通信的实现。最后通过一个完整的温度监控系统项目实战,展示如何用WPF构建实时数据采集界面,包括Modbus通信类编写、数据采集服务实现等关键代码片段。全文采用图解+代码的方式,帮助开发者快速掌握工控系统

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 704

模型压缩技术:剪枝、量化与知识蒸馏实战

模型压缩技术:剪枝、量化与知识蒸馏实战,在深度学习领域,模型的性能往往与模型的规模紧密相关,更大的模型通常能学习到更复杂的模式,从而在任务中取得更好的效果。然而,随着模型规模的不断增大,其在实际应用中面临着诸多挑战,如内存占用高、计算资源需求大、推理速度慢等问题,这使得在资源受限的设备(如移动设备、嵌入式设备)上部署变得困难重重。模型压缩技术应运而生,它旨在在尽可能保持模型性能的前提下,通过各种方法减少模型的参数数量和计算量,提高模型的效率和可部署性。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 5万+

C++工程,rapidjson字符串为空或乱码,rapidjson超长字符串,rapidjson超大数据json串包不住

使用rapidjson时出现以上问题,1.不是完整的内容,2.多次转义\ bid.AddMember(“adm”, rapidjson::StringRef(html_snippet.c_str(),html_snippet.size()), allocator); stringRef(html_snippet.c_str())一开始以为可能可能是字符串结束标志问题,这种方式会调动C的strl...

m0_37542524的博客 4417

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

实现序列化和反序列化

在C++中实现JSON序列化和反序列化,一个常用的第三方库是RapidJSON,它是一个快速的JSON解析器及生成器,适用于效率敏感的应用场景。下面我将给出使用RapidJSON进行JSON序列化和反序列化的基础示例。请注意,以上示例假定你已经正确安装并配置了RapidJSON库。此外,对于更复杂的对象结构,你可能需要实现更复杂的逻辑来遍历和设置JSON文档的成员。### JSON反序列化(JSON字符串转换为对象)### JSON序列化(对象转换为JSON字符串)// 假设这是你要序列化的类或结构体。

weixin_43803780的博客 1547

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

突破JSON性能瓶颈:RapidJSON性能调优终极指南

在现代C++开发中,JSON数据处理的性能往往成为系统瓶颈。RapidJSON作为一款高性能的C++ JSON解析器/生成器,通过一系列优化技术帮助开发者突破性能瓶颈。本文将深入解析RapidJSON的性能优化秘籍,让你的应用飞起来!🚀 ## 什么是RapidJSON? RapidJSON是一个专为C++设计的高性能JSON解析器和生成器,支持SAX和DOM两种API风格。根据官方性能测试,

gitblog_00540的博客 1150

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

极速JSON校验:RapidJSON Schema验证实战指南

RapidJSON是一个C++快速JSON解析器和生成器,支持SAX和DOM风格API。本文将详细介绍如何使用RapidJSON的Schema验证功能,帮助开发者轻松实现JSON数据的格式校验,确保数据交换的准确性和可靠性。 ## 什么是JSON Schema验证? JSON Schema是一种描述JSON数据格式的草案标准,其本身也是JSON数据。通过JSON Schema验证JSON结构,

gitblog_00455的博客 1252
上一篇: 【7】cpp_redis hash容器 增删改查(避免死锁的解决方法) 【最后更新于2018-05-05】
下一篇: 【9】cpp_redis RapidJson redis (C++对象利用Rapidjson序列化到redis与反序列化)
C++程序员Carea
博客等级 码龄18年 1590粉丝 878原创
评论 8
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C++程序员Carea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值