You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中while循环避免`*branch`多次可变借用的解决方案

解决serde_json树形结构转换中的可变借用编译错误

需求说明

输入JSON结构:

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

期望转换后的输出JSON:

{"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:插入新节点后又立即获取其可变引用,导致编译器判定违反借用规则。如果能一步完成插入并获取引用,就能解决问题——类似std::collections::HashMap的try_insert方法的效果。

尝试用entry方法合并插入与获取操作,改写后的代码如下:

use serde_json::{Map, Value};
use std::collections::VecDeque;

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)
}

内容的提问来源于stack exchange,提问作者ComplicatedPhenomenon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 18:24:50