我正在try 实现将如下所示的json作为输入的逻辑

[{"key": "a", "children": [{"key": "a1", "children": [{"key": "a11", "children": []}]}]}, {"key": "b", "children": [{"key": "b1", "children": [{"key": "b11", "children": []}]}]}] 

而预期yields 是

{"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

我多次使用branch作为可变变量的原因是,我必须获取对我刚刚插入到映射中的内容的可变引用,如果我可以一次完成这两个步骤,那么问题就解决了.

我想如果serde_json::Map有一个类似于std::collections::HashMaptry_insert的方法,我的问题就解决了.


即使我把前面提到的两个步骤结合在一起, 我只是想知道,实际上我在每次迭代中都在不断地borrow branch,这也算"more than once at a time"吗?

fn insert_and_get<'a>(map: &'a mut Map<String, Value>, key: String, value: Value) -> &'a mut Value {
    map.entry(key).or_insert(value)
}


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 = json!({});
                let zed = insert_and_get(branch, key.to_owned(), child_branch).as_object_mut().unwrap();
                queue.push_back((children, zed));
            } else {
                branch.insert(key.to_owned(), serde_json::Value::String("".to_owned()));
            }
        }
    }
    serde_json::Value::Object(tree)
}

推荐答案

这是一个迭代的解决方案.

use serde_json::{Map, Value};

pub fn convert_tree(list: &[Value]) -> Option<Value> {
    // Contains a tuple of:
    // - the parent list as an iterator
    // - the parent map
    // - the key that the current map/iterator belongs to in the parent map
    let mut stack: Vec<(std::slice::Iter<Value>, Map<String, Value>, String)> = vec![];
    // Iterator of all the items that go into the current map
    let mut current_iter = list.iter();
    // Map containing all the items that we have consumed from the iterator
    let mut current_map = Map::new();

    // Loop until the stack is empty.
    //
    // Normally I'd do `while let Some(item) = stack.pop()`, but since we start with an item
    // in-progress (known to be an array), the pop isn't the first thing in the loop, so `while`
    // can't be used.
    let final_map = loop {
        // There are more items in the current iterator, so we must descend into the tree.
        if let Some(next) = current_iter.next() {
            // Validation
            let obj = next.as_object()?;
            let key = obj.get("key")?.as_str()?;
            let children = obj.get("children")?.as_array()?;

            // Push the current state onto the stack
            stack.push((current_iter, current_map, key.to_owned()));

            // Descend the tree
            current_iter = children.iter();
            current_map = Map::new();

        // There are no more items in the current iterator, so we must insert this result to the
        // current map.
        } else if let Some((parent_iter, mut parent_map, key)) = stack.pop() {
            // Insert the current map the parent map
            if current_map.is_empty() {
                // Transform any `{}` values into `""`
                parent_map.insert(key, Value::String("".to_owned()));
            } else {
                // Maps with contents are inserted unchanged
                parent_map.insert(key, Value::Object(current_map));
            }

            // Ascend the tree
            current_iter = parent_iter;
            current_map = parent_map;

        // There are no more parents, so this is the fully-formed answer
        } else {
            break current_map;
        }
    };

    Some(Value::Object(final_map))
}

我把&Vec<Value>改成了&[Value] for reasons explained here.作为最小的错误处理,我还返回了Option<Value>.

我已经try 在三个方面尽可能地使其可重构.首先是验证.

// Validation
let obj = next.as_object()?;
let key = obj.get("key")?.as_str()?;
let children = obj.get("children")?.as_array()?;

如果使函数接受更强的类型,则不需要这样做.例如,您可以使用以下命令:

#[derive(Deserialize)]
pub struct KeyAndChildren {
    key: String,
    children: Vec<KeyAndChildren>,
}

pub fn convert_tree(list: &[KeyAndChildren]) -> Value { ... }

这样,验证就转移到了调用方,你的函数不再需要错误路径.

第二,空字符串的特殊情况.

if current_map.is_empty() {
    // Transform any `{}` values into `""`
    parent_map.insert(key, Value::String("".to_owned()));
} else {
    // Maps with contents are inserted unchanged
    parent_map.insert(key, Value::Object(current_map));
}

如果您可以为空映射接受{}而不是"",则此条件是不必要的,并且始终可以使用第二个分支.

第三,是否消费 list .如果在调用convert_tree之后不需要该列表,则可以通过使用该列表来避免所有字符串分配.

pub fn convert_tree(list: &[Value]) -> Option<Value>
pub fn convert_tree(list: Vec<Value>) -> Option<Value>

在函数内部,您将使用into_iter而不是iter,并匹配Value个变体以获得它们自己的内容.

// Validation
let Value::Object(mut obj) = next else {
    return None;
};
let Value::String(key) = obj.get_mut("key")?.take() else {
    return None;
};
let Value::Array(children) = obj.get_mut("children")?.take() else {
    return None;
};

使用所拥有的值还允许您使用 struct 以增量方式进行验证.这里我使用的是Vec<Value>,而不是上面的Vec<KeyAndChildren>,因为我需要使用children来创建一个超过Value的迭代器.

#[derive(serde::Deserialize)]
struct KeyAndChildren {
    key: String,
    children: Vec<Value>,
}
let KeyAndChildren { key, children } = serde_json::from_value(next).ok()?;

Here's both borrowed and owned versions on playground.

Rust相关问答推荐

程序退出后只写入指定管道的数据

为什么幻影数据不能自动推断?

如何找到一个数字在二维数组中的位置(S)?

访问Rust中的隐藏变量

创建包含缺失值的框架

如何使用 list 在Rust for Windows中编译?

有没有办法指定只在Rust的测试中有效的断言?

如何在Rust中将选项<;选项<;字符串>;转换为选项<;选项&;str>;?

我可以在不收集或克隆的情况下,将一个带有Item=(key,val)的迭代器拆分成单独的key iter和val iter吗?

Rust中WPARAM和VIRTUAL_KEY的比较

如何将带有嵌套borrow /NLL 的 Rust 代码提取到函数中

当在lambda中通过引用传递时,为什么会出现终身/类型不匹配错误?

是否可以通过可变引用推进可变切片?

分配给下划线模式时会发生什么?

rust tokio::spawn 在 mutexguard 之后等待

如何将参数传递给Rust 的线程?

n 个范围的笛卡尔积

Rust 异步和 AsRef 未被发送

意外的正则表达式模式匹配

返回 &str 但不是 String 时,borrow 时间比预期长