如何合并(包括嵌套数组值)两个 serde_yaml::Value 对象?
how to combine (including nested array values) two serde_yaml::Value objects?
我在创建递归函数来解析两个 serde_yaml::Value 变量并将它们合并时遇到问题。在基层对象中组合它们很容易,但是子层值只是组合值的值。
鉴于:
let original:serde_yaml::Value = serde_yaml::from_str(r#"
keyA:
subKeyA:
- A
- B
- C
keyB: "one"
keyC: "a"
"#
).unwrap();
let add_or_modify_these_values:serde_yaml::Value = serde_yaml::from_str(r#"
keyA:
subKeyA:
- D
subKeyB:
- BA
keyB: "two"
keyC:
- A
- B
"#
).unwrap();
我将如何组合它们以便考虑所有嵌套属性,例如:
keyA:
subKeyA:
- A
- B
- C
- D
subKeyB:
- BA
keyB: "two"
keyC:
- A
- B
当出现复杂情况时(例如,像 keyC 这样的不同值类型),我更愿意用新值类型覆盖原始值类型。
编辑:我也在此处查看了 json 的类似问题:
但该合并方法不会合并数组值,只会覆盖。
编辑:已标记正确答案。将把这个留给 JSON 版本。
json 版本:
fn merge(a: &mut serde_json::Value, b: serde_json::Value) {
match (a, b) {
(a @ &mut serde_json::Value::Object(_), serde_json::Value::Object(b)) => {
let a = a.as_object_mut().unwrap();
for (k, v) in b {
if v.is_array() && a.contains_key(&k) && a.get(&k).as_ref().unwrap().is_array() {
let mut _a = a.get(&k).unwrap().as_array().unwrap().to_owned();
_a.append(&mut v.as_array().unwrap().to_owned());
a[&k] = serde_json::Value::from(_a);
}
else{
merge(a.entry(k).or_insert(serde_json::Value::Null), v);
}
}
}
(a, b) => *a = b,
}
}
我已经弄清楚了下面的转换(可能需要一些清理):
fn merge_yaml(a: &mut serde_yaml::Value, b: serde_yaml::Value) {
match (a, b) {
(a @ &mut serde_yaml::Value::Mapping(_), serde_yaml::Value::Mapping(b)) => {
let a = a.as_mapping_mut().unwrap();
for (k, v) in b {
if v.is_sequence() && a.contains_key(&k) && a[&k].is_sequence() {
let mut _b = a.get(&k).unwrap().as_sequence().unwrap().to_owned();
_b.append(&mut v.as_sequence().unwrap().to_owned());
a[&k] = serde_yaml::Value::from(_b);
continue;
}
if !a.contains_key(&k) {a.insert(k.to_owned(), v.to_owned());}
else { merge_yaml(&mut a[&k], v); }
}
}
(a, b) => *a = b,
}
}
这是一个 cleaned-up 版本(与 #![feature(let_chains)]
一起使用):
fn merge_yaml(a: &mut serde_yaml::Value, b: serde_yaml::Value) {
match (a, b) {
(serde_yaml::Value::Mapping(ref mut a), serde_yaml::Value::Mapping(b)) => {
for (k, v) in b {
if let Some(b_seq) = v.as_sequence()
&& let Some(a_val) = a.get(&k)
&& let Some(a_seq) = a_val.as_sequence()
{
a[&k] = [a_seq.as_slice(), b_seq.as_slice()].concat().into();
continue;
}
if !a.contains_key(&k) {
a.insert(k, v);
}
else {
Self::merge_yaml(&mut a[&k], v);
}
}
}
(a, b) => *a = b,
}
}
我在创建递归函数来解析两个 serde_yaml::Value 变量并将它们合并时遇到问题。在基层对象中组合它们很容易,但是子层值只是组合值的值。
鉴于:
let original:serde_yaml::Value = serde_yaml::from_str(r#"
keyA:
subKeyA:
- A
- B
- C
keyB: "one"
keyC: "a"
"#
).unwrap();
let add_or_modify_these_values:serde_yaml::Value = serde_yaml::from_str(r#"
keyA:
subKeyA:
- D
subKeyB:
- BA
keyB: "two"
keyC:
- A
- B
"#
).unwrap();
我将如何组合它们以便考虑所有嵌套属性,例如:
keyA:
subKeyA:
- A
- B
- C
- D
subKeyB:
- BA
keyB: "two"
keyC:
- A
- B
当出现复杂情况时(例如,像 keyC 这样的不同值类型),我更愿意用新值类型覆盖原始值类型。
编辑:我也在此处查看了 json 的类似问题:
编辑:已标记正确答案。将把这个留给 JSON 版本。
json 版本:
fn merge(a: &mut serde_json::Value, b: serde_json::Value) {
match (a, b) {
(a @ &mut serde_json::Value::Object(_), serde_json::Value::Object(b)) => {
let a = a.as_object_mut().unwrap();
for (k, v) in b {
if v.is_array() && a.contains_key(&k) && a.get(&k).as_ref().unwrap().is_array() {
let mut _a = a.get(&k).unwrap().as_array().unwrap().to_owned();
_a.append(&mut v.as_array().unwrap().to_owned());
a[&k] = serde_json::Value::from(_a);
}
else{
merge(a.entry(k).or_insert(serde_json::Value::Null), v);
}
}
}
(a, b) => *a = b,
}
}
我已经弄清楚了下面的转换(可能需要一些清理):
fn merge_yaml(a: &mut serde_yaml::Value, b: serde_yaml::Value) {
match (a, b) {
(a @ &mut serde_yaml::Value::Mapping(_), serde_yaml::Value::Mapping(b)) => {
let a = a.as_mapping_mut().unwrap();
for (k, v) in b {
if v.is_sequence() && a.contains_key(&k) && a[&k].is_sequence() {
let mut _b = a.get(&k).unwrap().as_sequence().unwrap().to_owned();
_b.append(&mut v.as_sequence().unwrap().to_owned());
a[&k] = serde_yaml::Value::from(_b);
continue;
}
if !a.contains_key(&k) {a.insert(k.to_owned(), v.to_owned());}
else { merge_yaml(&mut a[&k], v); }
}
}
(a, b) => *a = b,
}
}
这是一个 cleaned-up 版本(与 #![feature(let_chains)]
一起使用):
fn merge_yaml(a: &mut serde_yaml::Value, b: serde_yaml::Value) {
match (a, b) {
(serde_yaml::Value::Mapping(ref mut a), serde_yaml::Value::Mapping(b)) => {
for (k, v) in b {
if let Some(b_seq) = v.as_sequence()
&& let Some(a_val) = a.get(&k)
&& let Some(a_seq) = a_val.as_sequence()
{
a[&k] = [a_seq.as_slice(), b_seq.as_slice()].concat().into();
continue;
}
if !a.contains_key(&k) {
a.insert(k, v);
}
else {
Self::merge_yaml(&mut a[&k], v);
}
}
}
(a, b) => *a = b,
}
}