在 C++ 中使用 YAML:用于解析和序列化的 yaml-cpp 库

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

在 C++ 中使用 YAML:yaml-cpp 库



YAML(YAML Ain't Markup Language)是一种人类可读的数据序列化格式,常用于配置文件、数据交换和存储结构化信息。在 C++ 中,有一个强大且易于使用的库 yaml-cpp 可用于处理 YAML。在本文中,我们将详细介绍如何安装、配置和使用 yaml-cpp 来解析和创建 YAML 文档。



安装 yaml-cpp



yaml-cpp 库适用于大多数平台。最简单的安装方式是通过包管理器:



  • Ubuntu/Debian: sudo apt-get install libyaml-cpp-dev
  • macOS(Homebrew): brew install yaml-cpp
  • Windows(vcpkg): vcpkg install yaml-cpp


也可以从源代码编译,从 GitHub 下载仓库并使用 CMake:



git clone https://github.com/jbeder/yaml-cpp.gitcd yaml-cppmkdir build && cd buildcmake ..makesudo make install


yaml-cpp 基础



该库提供了直观的 API 用于加载、修改和保存 YAML 数据。所有数据类型都存储在 YAML::Node 容器中,它可以是标量、序列(数组)或映射(字典)。



YAML 文件示例



考虑以下配置文件 config.yaml:



database:  host: localhost  port: 5432  name: myapp  credentials:    user: admin    password: secret123

server: workers: 4 timeout: 30.5 debug: true

allowed_ips: - 192.168.0.1 - 192.168.0.2 - 10.0.0.1


解析 YAML 文件



使用 YAML::LoadFile() 函数从文件加载数据:



#include <yaml-cpp/yaml.h>#include <iostream>#include <string>#include <vector>

int main() { try { // 加载 YAML 文件 YAML::Node config = YAML::LoadFile("config.yaml");

// 通过运算符 [] 访问嵌套数据 std::string host = config["database"]["host"].as<std::string>(); int port = config["database"]["port"].as<int>(); std::string user = config["database"]["credentials"]["user"].as<std::string>();

std::cout << "Database host: " << host << std::endl; std::cout << "Database port: " << port << std::endl; std::cout << "User: " << user << std::endl;

// 处理序列(列表) YAML::Node ips = config["allowed_ips"]; std::vector<std::string> ipList; for (const auto& ip : ips) { ipList.push_back(ip.as<std::string>()); }

std::cout << "Allowed IPs: "; for (const auto& ip : ipList) { std::cout << ip << " "; } std::cout << std::endl;

} catch (const YAML::Exception& e) { std::cerr << "YAML Error: " << e.what() << std::endl; return 1; }

return 0;}


创建和序列化 YAML



yaml-cpp 还允许以编程方式创建 YAML 文档并将其保存到文件:



#include <yaml-cpp/yaml.h>#include <fstream>

int main() { // 创建根节点 YAML::Node config;

// 添加数据 config["application"]["name"] = "MyApp"; config["application"]["version"] = 2.1; config["application"]["debug"] = false;

// 创建序列 config["features"].push_back("logging"); config["features"].push_back("caching"); config["features"].push_back("auth");

// 将配置写入文件 std::ofstream fout("output.yaml"); fout << config; fout.close();

return 0;}


处理复杂数据类型



yaml-cpp 支持自定义类型的序列化和反序列化。您需要为您的类型提供 YAML::convert<> 模板特化:



struct Point {    double x, y;};

namespace YAML {template<>struct convert<Point> { static Node encode(const Point& rhs) { Node node; node["x"] = rhs.x; node["y"] = rhs.y; return node; }

static bool decode(const Node& node, Point& rhs) { if(!node.IsMap() || node.size() != 2) return false; rhs.x = node["x"].as<double>(); rhs.y = node["y"].as<double>(); return true; }};}

int main() { YAML::Node node; node["point"] = Point{3.14, 2.71};

Point p = node["point"].as<Point>(); std::cout << "Point: (" << p.x << ", " << p.y << ")" << std::endl;

return 0;}


错误处理



处理 YAML 文件时,始终使用 try-catch 块捕获 YAML::Exception 非常重要。常见的异常包括:



  • YAML::BadFile — 文件无法打开或读取
  • YAML::ParserException — YAML 语法错误
  • YAML::RepresentationException — 类型转换错误


最佳实践



  1. 始终验证数据: 使用 IsDefined()、IsScalar()、IsSequence() 和 IsMap() 方法检查节点类型。
  2. 使用默认值: 如果键可能缺失,使用 as<T>(defaultValue) 提供默认值。
  3. 避免深层嵌套: 深度嵌套的 YAML 结构难以阅读和维护。尽量保持层次结构平坦。
  4. 使用锚点和别名: YAML 支持锚点(&)和别名(*)以避免重复数据。
  5. 文档化您的配置: 在 YAML 文件中添加注释以解释每个设置的目的。


结论



yaml-cpp 是一个功能强大且灵活的库,用于在 C++ 中处理 YAML 数据。它提供了简单的 API 用于解析、创建和序列化 YAML 文档,并支持自定义类型。无论您是处理配置文件、数据交换格式还是任何其他结构化数据,yaml-cpp 都是 C++ 开发者的绝佳选择。



有关更多信息,请访问官方 yaml-cpp GitHub 仓库。

推荐