一.意義
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就會丢出一個異常。