yaml 使用自定义类型读取和写回文件 .as<struce> 和emitter 以及随机出现解析失败警告

一.意义
 yaml对于内容有类型判断,也可以通过!!进行指定类型,所以这给读取自定义结构类型的yaml读取提供了可以,而不是在yaml 0.5以后的版本中还需要重载一大堆的>>符号

二.参考资料
yaml-cpp官网
https://github.com/jbeder/yaml-cpp/wiki/Tutorial

node.Type()
-Null
-Scalar
-Sequence
-map
-undefined

三.读取
重载yaml命名空间里面的decode函数

struct Vec3 { double x, y, z;};
namespace YAML {
template<>
struct convert<Vec3> {
  static bool decode(const Node& node, Vec3& rhs) {
    if(!node.IsSequence() || node.size() != 3) {
      return false;
    }
    rhs.x = node[0].as<double>();
    rhs.y = node[1].as<double>();
    rhs.z = node[2].as<double>();
    return true;
  }
};
}
YAML::Node node = YAML::Load("start: [1, 3, 0]");
Vec3 v = node["start"].as<Vec3>();
node["end"] = Vec3(2, -1, 0);


来一个复杂一点的
yaml数据为:

-name:marry
 id:10
 sex:female
 workday:[1,2,5,6]

-name:dave
 id:11
 sex:male
 workday:[2,3,4,5]

定义结构体为

struct employee
{
 string name;
 int id;
 string sex;
 struct workDay{double one,two,three,four};
}

这个时候重载decode函数为   
//decode

//其实decode函数就是告诉yaml怎么把yaml读取后的数组的内容和自定义数据类型进行复制
static bool decode(const Node& node, employee& subdata) {//一个"-"表示一个node

    subdata.name = node[0].as<string>();
    subdata.id = node[1].as<int>();     //这个时候类型只能是int 否则也会解析失败
    subdata.sex = node[2].as<double>(); //还可以在decode里面做内容的判断
    if(subdata.sex!="male"||subdata.sex!="female")
    return false;//函数最后return false会throw 一个exception 需要话在使用node.as<employee>的时候使用try catch去捕获异常
    subData.workDay.one=node[3][0].as<double>();
    subData.workDay.two=node[3][1].as<double>();
    subData.workDay.three=node[3][2].as<double>();
    subData.workDay.four=node[3][3].as<double>();
    return true;
}


//解析失败原因
1.访问了一个node数组为空的项
2.内容类型和指定as解析的不同,例如 id=ss这个时候就会报错了 as支持c++八大基本类型
3.和decode函数里面设定的条件不同 sex=man 这个时候也会throw一个exception
通过try catch 抓住yaml exception&e之后 可以通过e.what来显示集体是哪一行出了问题
//可以用node["name"]同样能够读取的到

四、写回


yaml-cpp 0.5之后就不在使用encode这个重载函数,而是使用了一个emiter对象,所以需要在使用写回yaml文件的类中声明emiter的<<为重载函数
一个emiter就相当是一个文件对象 同样的<<主要就是声明怎么把 自定义的类型数据和node建立一一对应的联系

struct employee
{
 string name;
 int id;
 string sex;
 struct workDay{double one,two,three,four};
}
YAML::Emitter& operator << (YAML::Emitter& out, const employee& v) {
    <out<YAML::BeginSeq;//声明一个文件开始 --- 关于---和...可以参考https://blog.csdn.net/qq_34249583/article/details/81166216

    out << YAML::BeginMap
    out << YAML::Key<<"name";//name代表的是yaml文件里面的key名字和employee的name没有直接关联
    out << YAML::Value<<v.name;
    
    out <<YAML::Key<<"id";
        out <<YAML::Value<<v.id;

        out <<YAML::Key<<"sex"
        out <<YAML::Value<<v.sex;

        out <<YAML::Key<<"workDay";
        vector<double> workday<<v.workDay.one<<v.workDay.two<<v.workDay.three<<v.workDay.four;
    out <<YAML::Value<<YAML::Flow<<workday;
    out <<YAML::EndMap;

    out << YAML::EndSeq;//声明一个文件结束 ...
        return out;
}

写完对应关系之后就是使用
YAML::Emitter emit;
emit<<employee;
file<<emit.c_str();

五、随机失败警告

      解析字符有时候能够解析成功,但是有时候又会随机报错,这种情况通常来说是因为重载decode函数的时候,并不是所有路径上都有返回值,导致函数return了一个随机值,这个函数一旦return false,yaml-cpp就会丢出一个异常。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`@PropertySource`注解默认只支持`.properties`格式的配置文件,不支持`.yaml`和`.yml`格式的配置文件。如果需要读取`.yaml`或`.yml`格式的配置文件,可以使用`@ConfigurationProperties`注解来读取。 假设我们有一个`application.yml`配置文件,在其中定义了一个`my.package`变量,我们可以按照以下方式在`RestControllerAdvice`中使用它: 1. 在`application.yml`中定义变量: ```yaml my: package: com.example.myapp ``` 2. 在`RestControllerAdvice`中使用`@ConfigurationProperties`注解读取配置文件中的变量: ```java @ConfigurationProperties(prefix = "my") public class MyProperties { private String package; public String getPackage() { return package; } public void setPackage(String packageName) { this.package = packageName; } } @RestControllerAdvice(basePackages = "#{@myProperties.package}") public class MyRestControllerAdvice { // ... } ``` 在这个例子中,`@ConfigurationProperties`注解用于读取`application.yml`中的`my.package`属性,并将其映射为`MyProperties`对象的`package`属性。然后,我们可以使用SpEL表达式`#{@myProperties.package}`来引用这个属性,从而指定了`MyRestControllerAdvice`所要扫描的包。需要注意的是,`@ConfigurationProperties`注解需要在Spring配置类中使用,并且要将`MyProperties`对象注册到Spring容器中。 这样,就可以使用`@ConfigurationProperties`注解来读取`.yaml`和`.yml`格式的配置文件,并将其中的变量传递给`basePackages`属性了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值