我正在尝试实现逻辑以如下所示的 json 作为输入
[{"key": "a", "children": [{"key": "a1", "children": [{"key": "a11", "children": []}]}]}, {"key": "b", "children": [{"key": "b1", "children": [{"key": "b11", "children": []}]}]}]
预期输出是
{"a": {"a1": {"a11": ""}}, "b": {"b1": {"b11": ""}}}
我的主要功能如下
use serde_json::{json, Value};
use std::{collections::VecDeque};
fn convert_tree(lst: &Vec<serde_json::Value>) -> serde_json::Value {
let mut tree = serde_json::Map::new();
let mut queue = VecDeque::new();
queue.push_back((lst, &mut tree));
while let Some((entries, branch)) = queue.pop_front() {
for entry in entries {
let key = entry["key"].as_str().unwrap();
let children = entry["children"].as_array();
if let Some(children) = children {
let child_branch = serde_json::Map::new();
branch.insert(key.to_owned(), serde_json::Value::Object(child_branch));
let mut branch_ref = branch.get_mut(key).unwrap().as_object_mut().unwrap();
queue.push_back((children, &mut branch_ref));
} else {
branch.insert(key.to_owned(), serde_json::Value::String("".to_owned()));
}
}
}
serde_json::Value::Object(tree)
}
#[test]
fn test_convert_tree(){
let a_str = r#"[{"key": "a", "children": [{"key": "a1", "children": [{"key": "a11", "children": []}]}]}, {"key": "b", "children": [{"key": "b1", "children": [{"key": "b11", "children": []}]}]}]"#;
let v: Vec<serde_json::Value>= serde_json::from_str(a_str).unwrap();
println!("{:#?}", v);
let zed = convert_tree(&v);
}
cargo test --package flashlight --example test_serde_json2 -- test_convert_tree --exact --nocapture
遇到错误
error[E0499]: cannot borrow `*branch` as mutable more than once at a time
--> examples/test_serde_json2.rs:68:17
|
68 | branch.insert(key.to_owned(), serde_json::Value::Object(child_branch));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
69 | let mut branch_ref = branch.get_mut(key).unwrap().as_object_mut().unwrap();
| ------------------- first mutable borrow occurs here
70 | queue.push_back((children, &mut branch_ref));
| -------------------------------------------- first borrow later used here
error[E0499]: cannot borrow `*branch` as mutable more than once at a time
--> examples/test_serde_json2.rs:69:38
|
62 | while let Some((entries, branch)) = queue.pop_front() {
| ----------------- first borrow used here, in later iteration of loop
...
69 | let mut branch_ref = branch.get_mut(key).unwrap().as_object_mut().unwrap();
| ^^^^^^^^^^^^^^^^^^^ `*branch` was mutably borrowed here in the previous iteration of the loop
error[E0597]: `branch_ref` does not live long enough
--> examples/test_serde_json2.rs:70:44
|
62 | while let Some((entries, branch)) = queue.pop_front() {
| ----------------- borrow later used here
...
70 | queue.push_back((children, &mut branch_ref));
| ^^^^^^^^^^^^^^^ borrowed value does not live long enough
71 | } else {
| - `branch_ref` dropped here while still borrowed
error[E0499]: cannot borrow `*branch` as mutable more than once at a time
--> examples/test_serde_json2.rs:72:17
|
62 | while let Some((entries, branch)) = queue.pop_front() {
| ----------------- first borrow later used here
...
69 | let mut branch_ref = branch.get_mut(key).unwrap().as_object_mut().unwrap();
| ------------------- first mutable borrow occurs here
...
72 | branch.insert(key.to_owned(), serde_json::Value::String("".to_owned()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
Some errors have detailed explanations: E0499, E0597.
For more information about an error, try `rustc --explain E0499`.
warning: `flashlight` (example "test_serde_json2" test) generated 1 warning
error: could not compile `flashlight` due to 4 previous errors; 1 warning emitted
对于此类问题,最简单的方法通常是递归。
fn convert_tree(lst: &[serde_json::Value]) -> serde_json::Value {
let tree = lst
.iter()
.map(|item| {
let key = item["key"].as_str().unwrap().to_owned();
let children = if let Some(children) = item["children"].as_array() {
convert_tree(children)
} else {
Value::String("".to_owned())
};
(key, children)
})
.collect();
serde_json::Value::Object(tree)
}