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
相关产品推荐
相关产品推荐

