C++使用JsonCpp库:编译、读写JSON及网络传输示例
在C++开发中,JsonCpp是处理JSON数据的经典轻量级库。本文将指导用户如何从源码编译JsonCpp以获取静态链接库,并详细解析其核心的Value、Reader和Writer类的用法。通过反序列化解析、序列化生成以及UDP Socket网络传输三个完整示例,展示如何在C++环境中高效创建和操作JSON数据。
准备工作:编译JsonCpp获取静态库
首先,需要从官方SourceForge仓库下载jsoncpp的最新版本源码包(通常是tar.gz格式)。解压后,找到工程文件并在Visual Studio中打开进行编译。编译成功后,在输出目录(例如 build/vs71/debug/lib_json)下即可找到生成的 .lib 静态链接库文件,将其链接到项目中即可使用。
注意: JsonCpp的所有类和命名空间均位于 namespace json 中,使用时只需包含 json.h 头文件。
核心组件说明
JsonCpp主要依赖三种核心类来操作JSON:
Json::Value:通用容器,可表示整数(int)、浮点数(double)、字符串(string)、对象(object)等所有支持的数据类型。Json::Reader:用于反序列化。将文件或字符串中的JSON文本解析为Json::Value树状结构,主要调用parse()函数。Json::Writer:用于序列化。将Json::Value转换为字符串流或文件输出。由于它是一个纯虚类不能直接使用,通常使用其子类:Json::FastWriter:快速写入,无格式化输出。Json::StyledWriter:美观格式输出。Json::StyledStreamWriter:适合大文件的流式风格写入。
第一步:JSON反序列化(解析数据)
此步骤演示如何将JSON格式的字符串解析为C++对象,并遍历其中的数组元素。
#include "json/json.h"
#include <iostream>
void ReadJson()
{
// JSON源字符串
std::string strValue = "{\"name\":\"xiaoming\",\"like\":[{\"book\":\"json\"},{\"food\":\"apple\"},{\"music\":\"sdds\"}]}";
Json::Reader reader; // 解析器
Json::Value value; // 根节点
// 尝试解析JSON字符串
if (reader.parse(strValue, value))
{
// 提取简单字段
std::string out = value["name"].asString();
std::cout << "Name: " << out << std::endl;
// 遍历数组字段
const Json::Value arrayObj = value["like"];
for (unsigned int i = 0; i < arrayObj.size(); i++)
{
// 检查键是否存在,避免崩溃
if (!arrayObj[i].isMember("book"))
continue;
out = arrayObj[i]["book"].asString();
std::cout << "Book: " << out;
if (i != (arrayObj.size() - 1))
std::cout << std::endl;
}
}
}
第二步:JSON序列化(生成数据)
此步骤演示如何构造C++数据对象,并将其序列化为可读性强的JSON字符串。
#include "json/json.h"
#include <iostream>
void WriteJson()
{
Json::Value root; // 根节点
Json::Value arrayObj; // 数组节点
Json::Value item; // 子项节点
// 构建内部对象
item["food"] = "apple";
item["music"] = "JZhou";
item["book"] = "json";
// 将子项加入数组
arrayObj.append(item);
// 设置根节点属性
root["name"] = "xiaoming";
root["like"] = arrayObj;
// 格式化为字符串并输出
std::string out = root.toStyledString();
std::cout << out << std::endl;
}
第三步:通过网络Socket传输JSON数据
在实际应用中,经常需要在网络间传递JSON数据。以下示例展示了基于Windows环境UDP协议的客户端发送与服务端接收过程。
服务端:接收并解析JSON
服务端创建Socket绑定端口,接收缓冲区数据后使用 Reader 解析内容。
#include <iostream>
#include <WinSock2.h>
#include "json/json.h"
#pragma comment(lib, "WS2_32.lib")
#pragma comment(lib, "json_vc71_libmtd.lib")
int main()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData); // 初始化Socket环境
SOCKET RecvSocket;
sockaddr_in RecvAddr;
int Port = 27015;
RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY); // 监听任意IP
bind(RecvSocket, (SOCKADDR*)&RecvAddr, sizeof(RecvAddr));
char RecvBuf[1024];
int BufLen = 1024;
sockaddr_in SenderAddr;
int SendAddrSize = sizeof(SenderAddr);
// 阻塞接收数据
recvfrom(RecvSocket, RecvBuf, BufLen, 0, (SOCKADDR*)&SenderAddr, &SendAddrSize);
std::string strName;
Json::Value val;
Json::Reader reader;
// 解析接收到的JSON字符串
if (reader.parse(RecvBuf, val))
{
strName = val["name"].asString();
}
std::cout << "Received Name: " << strName << std::endl;
closesocket(RecvSocket);
WSACleanup();
getchar();
return 0;
}
客户端:构造JSON并发送
客户端使用 StyledWriter 将Value对象转为字符串,并通过UDP协议发送到指定IP和端口。
#include "json/json.h"
#include <WinSock2.h>
#include <iostream>
#pragma comment(lib, "WS2_32.lib")
#pragma comment(lib, "json_vc71_libmtd.lib")
int main()
{
Json::Value val;
Json::StyledWriter style_write;
// 构造JSON数据
val["name"] = "xiaoli";
WSADATA wsaData;
SOCKET SendSocket;
sockaddr_in RecvAddr;
int Port = 27015;
WSAStartup(MAKEWORD(2, 2), &wsaData); // 初始化Socket
SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // 创建UDP Socket
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 目标服务器地址
// 将Json::Value序列化为字符串
std::string SendBuf = style_write.write(val);
// 发送数据包
sendto(SendSocket, SendBuf.c_str(), SendBuf.size(), 0, (SOCKADDR*)&RecvAddr, sizeof(RecvAddr));
std::cout << "Message sent." << std::endl;
closesocket(SendSocket);
WSACleanup();
getchar();
return 0;
}
以上就是C++使用JsonCpp库进行JSON数据处理和网络传输的详细内容,更多关于C++开发技巧的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









