转换错误类型
在某些情况下,某种格式的值必须包含在另一种格式的数据中。例如,Terraform 中的IAM策略被表示为包含在HCL配置中的JSON字符串。
将内部值视为简单的字符串可能很简单,但是如果我们要操作内部和外部值,则通常将它们一次性序列化和反序列化会更方便。
在这种情况下,偶尔会遇到的绊脚石是正确处理错误。这两种格式(很可能)具有不同的错误类型,因此需要进行一些转换。
此示例显示包含简化IAM策略的简化 HCL 资源。在序列化时,策略文档被表示为 JSON 字符串。
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct Resource {
name: String,
#[serde(with = "as_json_string")]
policy: Policy,
}
#[derive(Serialize, Deserialize)]
struct Policy {
effect: String,
action: String,
resource: String,
}
// 用于处理表示为 JSON 字符串的嵌套值的序列化和反序列化逻辑。
mod as_json_string {
use serde_json;
use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, DeserializeOwned, Deserializer};
// 序列化为 JSON 字符串,然后将字符串序列化为输出格式。
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
T: Serialize,
S: Serializer,
{
use serde::ser::Error;
let j = serde_json::to_string(value).map_err(Error::custom)?;
j.serialize(serializer)
}
// 从输入格式中反序列化字符串,然后将该字符串的内容反序列化为 JSON。
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
T: DeserializeOwned,
D: Deserializer<'de>,
{
use serde::de::Error;
let j = String::deserialize(deserializer)?;
serde_json::from_str(&j).map_err(Error::custom)
}
}
fn main() {
let resource = Resource {
name: "test_policy".to_owned(),
policy: Policy {
effect: "Allow".to_owned(),
action: "s3:ListBucket".to_owned(),
resource: "arn:aws:s3:::example_bucket".to_owned(),
},
};
let y = serde_yaml::to_string(&resource).unwrap();
println!("{}", y);
}