You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.21 03:45:07