C++ 基于PICOJSON与Pugixml实现动态JSON转XML的方法求助
你贴的picojson::parse相关代码已经可以完成JSON字符串到picojson对象的转换,建议补充解析成功后的类型校验,避免后续操作非法类型报错:
picojson::parse(v, json, json + strlen(json), &err); if (!err.empty()) { std::cerr << "JSON解析错误: " << err << std::endl; return 1; } // 校验顶层是JSON对象,符合你给出的测试用例结构 if (!v.is<picojson::object>()) { std::cerr << "JSON顶层不是对象结构" << std::endl; return 1; }
完整JSON转XML实现代码
转换逻辑遵循以下默认规则,你可以根据业务需求自行调整:
- JSON对象的键作为XML子节点的标签名
- JSON数组的每个元素统一用
<item>作为标签 - 字符串、数字、布尔、null类型直接作为节点文本内容
完整可运行代码如下:
#include <iostream> #include <string> #include "picojson.h" #include "pugixml.hpp" using namespace std; // 递归转换picojson值到pugixml节点 void json_to_xml(const picojson::value& json_val, pugi::xml_node& xml_node) { if (json_val.is<picojson::object>()) { // 处理JSON对象:遍历每个键值对生成子节点 const picojson::object& obj = json_val.get<picojson::object>(); for (const auto& pair : obj) { pugi::xml_node child = xml_node.append_child(pair.first.c_str()); json_to_xml(pair.second, child); } } else if (json_val.is<picojson::array>()) { // 处理JSON数组:每个元素生成item子节点 const picojson::array& arr = json_val.get<picojson::array>(); for (const auto& item : arr) { pugi::xml_node item_node = xml_node.append_child("item"); json_to_xml(item, item_node); } } else if (json_val.is<std::string>()) { // 处理字符串类型 xml_node.append_child(pugi::node_pcdata).set_value(json_val.get<std::string>().c_str()); } else if (json_val.is<double>()) { // 处理数字类型,格式化后存储 string num_str = to_string(json_val.get<double>()); // 去掉整数末尾多余的.0 if (num_str.find('.') != string::npos) { num_str.erase(num_str.find_last_not_of('0') + 1, string::npos); num_str.erase(num_str.find_last_not_of('.') + 1, string::npos); } xml_node.append_child(pugi::node_pcdata).set_value(num_str.c_str()); } else if (json_val.is<bool>()) { // 处理布尔类型 xml_node.append_child(pugi::node_pcdata).set_value(json_val.get<bool>() ? "true" : "false"); } else if (json_val.is<picojson::null>()) { // 处理null类型 xml_node.append_child(pugi::node_pcdata).set_value("null"); } } int main() { const char* json = "{\"menu\": {" "\"id\": \"f\"," "\"popup\": {" " \"menuitem\": [" " {\"v\": \"0\"}," " {\"v\": \"1\"}," " {\"v\": \"2\"}" " ]" " }" "}" "}"; picojson::value v; std::string err; const char* json_end = picojson::parse(v, json, json + strlen(json), &err); if (!err.empty()) { std::cerr << "JSON解析错误: " << err << std::endl; return 1; } if (!v.is<picojson::object>()) { std::cerr << "JSON顶层不是对象结构" << std::endl; return 1; } // 初始化XML文档 pugi::xml_document doc; // 添加XML声明 pugi::xml_node decl = doc.prepend_child(pugi::node_declaration); decl.append_attribute("version") = "1.0"; decl.append_attribute("encoding") = "UTF-8"; // 执行递归转换 json_to_xml(v, doc); // 输出XML到标准输出,也可以调用save_file方法存储到本地文件 doc.save(std::cout, " "); return 0; }
输出结果示例
运行上述代码会生成以下XML结构:
<?xml version="1.0" encoding="UTF-8"?> <menu> <id>f</id> <popup> <menuitem> <item> <v>0</v> </item> <item> <v>1</v> </item> <item> <v>2</v> </item> </menuitem> </popup> </menu>
如果需要调整节点命名规则(比如数组节点不用item而是用父节点名的单数形式)、或者把值存为节点属性而非子节点文本,直接修改json_to_xml递归函数的对应逻辑即可。
内容的提问来源于stack exchange,提问作者user804401
相关产品推荐
相关产品推荐

