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

如何遍历Rust serde对象键并修改字符串值?解决借用冲突

解决Serde JSON对象的HTML清理及可变借用冲突问题

错误原因

你遇到的编译错误是Rust借用规则导致的:当你通过doc.as_object_mut().unwrap()获取JSON对象的可变引用并遍历其键值对时,已经持有了整个对象的可变借用;此时再通过doc[field_name]尝试修改值,相当于再次请求对象的可变引用,违反了Rust“同一时间只能有一个可变引用”的规则,因此编译失败。

最优实现方式

直接遍历JSON对象的可变键值对,在遍历过程中直接修改字符串值,无需额外操作原对象,既符合借用规则,又高效简洁:

if let Some(docs) = chunk.response.docs.as_array_mut() {
    for doc in docs.iter_mut() {
        // 仅处理Object类型的JSON对象,避免非预期类型导致panic
        if let Some(obj) = doc.as_object_mut() {
            for (_key, value) in obj {
                // 匹配字符串类型的值,获取可变引用
                if let Value::String(ref mut s) = value {
                    // 替换为HTML清理后的字符串
                    *s = sanitize_html::sanitize_str(s);
                }
            }
        }
    }
}

代码说明

  • doc.as_object_mut()返回Option<&mut Map<String, Value>>,用if let替代unwrap()可以避免非Object类型时程序崩溃
  • 遍历obj的键值对时,value是&mut Value类型的可变引用,直接匹配Value::String(ref mut s)就能拿到字符串的可变引用
  • 对s解引用(*s)赋值,直接修改原字符串内容,不会触发借用冲突

备选方案(需收集键的场景)

如果需要先处理键的逻辑(比如过滤某些字段),可以先收集所有键的副本,再遍历键修改对应值:

if let Some(docs) = chunk.response.docs.as_array_mut() {
    for doc in docs.iter_mut() {
        if let Some(obj) = doc.as_object_mut() {
            // 收集所有键的克隆副本
            let keys: Vec<String> = obj.keys().cloned().collect();
            
            for key in keys {
                if let Some(Value::String(ref mut s)) = obj.get_mut(&key) {
                    *s = sanitize_html::sanitize_str(s);
                }
            }
        }
    }
}

这种方式适合需要对键做额外处理的场景,但会额外占用内存存储键的副本,性能略低于第一种方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 18:05:40