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

Rust中反序列化多对象JSON并提取指定字段的问题

解决serde_json解析多个独立JSON对象拼接字符串的问题

错误原因

你遇到的invalid type: map, expected a sequence错误,本质是原始输入不是合法的JSON数组。serde_json的from_str默认只能解析单个JSON值,而你提供的是多个独立JSON对象直接拼接的字符串(比如{...}{...}),解析器期望看到数组的起始符号[,但第一个字符是对象的{,因此报错。

解决方案

方案1:手动转换为合法JSON数组(简单但有局限)

如果能确保原始字符串里的对象内部不会出现}{这类字符,可以手动给输入包裹数组结构,同时在对象之间插入逗号:

use serde::Deserialize;
use serde_json::Error;

#[derive(Debug, Deserialize)]
struct AllFiles {
    target: Target,
}

#[derive(Debug, Deserialize)]
struct Target {
    test: bool,
    files: Vec<String>,
}

fn main() -> Result<(), Error> {
    // 原始多个独立JSON对象拼接的字符串
    let raw_json = r#"{"target":{"test":true,"files":["a.txt"]}}{"target":{"test":false,"files":["b.txt"]}}"#;
    
    // 转换为合法JSON数组
    let fixed_json = format!("[{}]", raw_json.replace("}{", "},{"));
    
    // 反序列化为Vec<AllFiles>
    let items: Vec<AllFiles> = serde_json::from_str(&fixed_json)?;
    
    // 提取所需字段
    for item in items {
        println!("test: {}, files: {:?}", item.target.test, item.target.files);
    }
    
    Ok(())
}

⚠️ 注意:如果原始JSON的字符串字段中包含}{(比如{"content": "}{"}),这种替换会破坏合法的JSON结构,导致解析失败。

方案2:使用serde_json流式解析(推荐,无局限)

serde_json提供了流式解析器,可以逐个读取并解析流中的每个顶层JSON值,无需修改原始字符串,是更可靠的方案:

use serde::Deserialize;
use serde_json::Deserializer;
use std::io::Read;

#[derive(Debug, Deserialize)]
struct AllFiles {
    target: Target,
}

#[derive(Debug, Deserialize)]
struct Target {
    test: bool,
    files: Vec<String>,
}

fn main() {
    let raw_json = r#"{"target":{"test":true,"files":["a.txt"]}}{"target":{"test":false,"files":["b.txt"]}}"#;
    
    // 将字符串包装为Read对象
    let mut reader = raw_json.as_bytes();
    
    // 创建流式解析器
    let deserializer = Deserializer::from_reader(&mut reader);
    
    // 逐个解析每个JSON对象
    let mut items = Vec::new();
    for result in deserializer.into_iter::<AllFiles>() {
        match result {
            Ok(item) => items.push(item),
            Err(e) => eprintln!("解析单个对象失败: {}", e),
        }
    }
    
    // 遍历提取目标字段
    for item in items {
        println!("test: {}, files: {:?}", item.target.test, item.target.files);
    }
}

这个方法会逐个处理输入中的每个独立JSON对象,不管它们之间是否有分隔符,完全避免了手动修改字符串带来的风险。

内容的提问来源于stack exchange,提问作者The official louwtreuh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 14:33:22