• c++ 解析yaml文件


    一直用c++操作ini做配置文件,想换成yaml,在全球最大的同性交友网站github上搜索,看有没有开源的库,功夫不负有心人,找到了yaml-cpp,试着解析了一个yaml文件,给个满分。分享一下如何使用他。
    git clone git@github.com:jbeder/yaml-cpp.git下,进行build四件套,把他编译成静态库

    mkdir build
    cd build
    cmake ..
    make
    

    运行完后,会得到libyaml-cpp.a
    新建一个项目,结构大致如下

    yaml_demo
      |__ include
             |__yaml-cpp 头文件夹
      |__ lib 
             |__yaml-cpp 库文件夹
      |__ main.cpp
    
    

    把头文件和库拷贝到相应的文件夹内。
    配置CMakeLists.txt把头文件和静态库加到项目里,这样在编译和链接时才能通过

    project(yaml_demo)
    set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) # 二进制文件的输出目录
    link_directories(${PROJECT_SOURCE_DIR}/lib/yaml-cpp)
    add_executable(${PROJECT_NAME} main.cpp)
    target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include)
    target_link_libraries(${PROJECT_NAME} yaml-cpp.a) 
    

    yaml-cpp的配置就完成了。看一下我的config文件

    api: aaaaa
    v: 1
    label:
      app: hello
      image: abc
    containers:
      - name: abc
        age: 18
      - name: 222
        age: 12
    

    其中apiv是比较简单的键值,我们可以直接读取他们的值

        std::cout << "api: " << config["api"].as<std::string>() << std::endl;
        std::cout << "v: " << config["v"].as<int>() << std::endl;
    

    label是一个mapcontainers是一个列表,这就要特殊处理一下,yaml-cpp有自己的转换模板

    template <typename T>
    struct convert;
    

    在进行转换的时候他会判断有没有实现 decode方法

    struct as_if<T, void> {
      explicit as_if(const Node& node_) : node(node_) {}
      const Node& node;
    
      T operator()() const {
        if (!node.m_pNode)
          throw TypedBadConversion<T>(node.Mark());
    
        T t;
        if (convert<T>::decode(node, t))
          return t;
        throw TypedBadConversion<T>(node.Mark());
      }
    };
    

    Nodeyaml-cpp的核心,我们的配置的所有操作都从这个类中进行。
    我们只要具体化自定义的struct就可以使用了

    struct label {
        std::string app;
        std::string image;
    };
    
    namespace YAML {
        template<>
        struct convert<label> {
            static Node encode(const label &rhs) {
                Node node;
                node.push_back(rhs.app);
                node.push_back(rhs.image);
                return node;
            }
    
            static bool decode(const Node &node, label &rhs) {
                std::cout << node.Type() << std::endl;
                rhs.app = node["app"].as<std::string>();
                rhs.image = node["image"].as<std::string>();
                return true;
            }
        };
    }
    

    encode 方法是把我们自定义的struct转换成yaml-cppNode
    转换时可以这样

    if (config["label"]) {
        label l = config["label"].as<label>();
        std::cout << "app: " << l.app << " image: " << l.image << std::endl;
    }
    

    container也是一样的具体化

    struct container {
        std::string name;
        int age;
    };
    
    namespace YAML {
        template<>
        struct convert<container> {
            static Node encode(const container &rhs) {
                Node node;
                node.push_back(rhs.name);
                node.push_back(rhs.age);
                return node;
            }
    
            static bool decode(const Node &node, container &rhs) {
                rhs.name = node["name"].as<std::string>();
                rhs.age = node["age"].as<int>();
                return true;
            }
        };
    }
    

    完整代码如下:

    #include <string>
    #include <iostream>
    #include <yaml-cpp/yaml.h>
    #include <yaml-cpp/node/parse.h>
    
    struct container {
        std::string name;
        int age;
    };
    
    namespace YAML {
        template<>
        struct convert<container> {
            static Node encode(const container &rhs) {
                Node node;
                node.push_back(rhs.name);
                node.push_back(rhs.age);
                return node;
            }
    
            static bool decode(const Node &node, container &rhs) {
                rhs.name = node["name"].as<std::string>();
                rhs.age = node["age"].as<int>();
                return true;
            }
        };
    }
    
    struct label {
        std::string app;
        std::string image;
    };
    
    namespace YAML {
        template<>
        struct convert<label> {
            static Node encode(const label &rhs) {
                Node node;
                node.push_back(rhs.app);
                node.push_back(rhs.image);
                return node;
            }
    
            static bool decode(const Node &node, label &rhs) {
                std::cout << node.Type() << std::endl;
                rhs.app = node["app"].as<std::string>();
                rhs.image = node["image"].as<std::string>();
                return true;
            }
        };
    }
    
    int main(int argc, char **argv) {
        std::string config_path = "./config.yaml";
        std::cout << config_path << std::endl;
        YAML::Node config = YAML::LoadFile(config_path);
    
        std::cout << "api: " << config["api"].as<std::string>() << std::endl;
        std::cout << "v: " << config["v"].as<int>() << std::endl;
    
        if (config["label"]) {
            label l = config["label"].as<label>();
            std::cout << "app: " << l.app << " image: " << l.image << std::endl;
        }
    
        if (config["containers"]) {
            std::vector<container> vi = config["containers"].as<std::vector<container>>();
    
            for (std::vector<container>::iterator it = vi.begin(); it != vi.end(); ++it) {
                std::cout << "vector: name: " << it->name << " age: " << it->age << std::endl;
            }
        }
    
        return 0;
    }
    
    
    
  • 相关阅读:
    C# 语言基础(++和--运算)
    Android RSA加密解密
    laravel redis
    larave5.1l队列
    shell更改目录编码
    Linux的权限说明
    MySQL主从架构之Master-Master互为主备
    php curl流方式远程下载大文件
    php session 跨页失效问题
    mysql中文字段转拼音首字母,以及中文拼音模糊查询
  • 原文地址:https://www.cnblogs.com/li-peng/p/14136068.html
Copyright © 2020-2023  润新知