zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
    
  • 相关阅读:
    严重: Parse error in application web.xml file at jndi:/localhost/ipws/WEBINF/web.xml java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml
    Failed to install .apk on device 'emulator5554': timeout解决方法
    java.lang.NoClassDefFoundError:org.jsoup.Jsoup
    Conversion to Dalvik format failed: Unable to execute dex:解决方法
    apache Digest: generating secret for digest authentication ...
    Description Resource Path Location Type Project has no default.properties file! Edit the project properties to set one.
    android service随机自启动
    MVC3 安装部署
    EF 4.3 CodeBased 数据迁移演练
    SQL Server 2008开启sa账户
  • 原文地址:https://www.cnblogs.com/li-peng/p/14136068.html
Copyright © 2011-2022 走看看