如何从 Rust 的文件/流中懒惰地读取多个 JSON 值?

6 serialization json rust

我想从 Rust 中的文件/读取器读取多个 JSON 对象,一次一个。不幸的是serde_json::from_reader(...)只读取到文件结束;似乎没有任何方法可以使用它来读取单个对象或懒惰地迭代对象。

有没有办法做到这一点?使用serde_json将是理想的,但如果有不同的库,我愿意使用它。

目前我将每个对象放在单独的行上并单独解析它们,但我真的不想这样做。

示例使用

主文件

use serde_json;

fn main() -> Result<(), Box<dyn std::error::Error>> {
   let stdin = std::io::stdin();
   let stdin = stdin.lock();

   for item in serde_json::iter_from_reader(stdin) {
     println!("Got {:?}", item);
   }

   Ok(())
}
Run Code Online (Sandbox Code Playgroud)

.txt

{"foo": ["bar", "baz"]} 1 2 [] 4 5 6
Run Code Online (Sandbox Code Playgroud)

示例会话

{"foo": ["bar", "baz"]} 1 2 [] 4 5 6
Run Code Online (Sandbox Code Playgroud)

小智 10

我想在 Python 中做到这一点时,这很痛苦,但幸运的是,在 Rust 中,这是事实标准serde_json板条箱的直接支持功能!它不是作为一个单一的便利函数公开的,但我们只需要从我们的文件/阅读器中创建一个serde_json::Deserializer读取,然后使用它的.into_iter()方法来获取一个StreamDeserializer迭代器,产生Result包含serde_json::ValueJSON 值的s 。

use serde_json; // 1.0.39

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let stdin = std::io::stdin();
    let stdin = stdin.lock();

    let deserializer = serde_json::Deserializer::from_reader(stdin);
    let iterator = deserializer.into_iter::<serde_json::Value>();
    for item in iterator {
        println!("Got {:?}", item?);
    }

    Ok(())
}
Run Code Online (Sandbox Code Playgroud)

需要注意的一件事是:如果遇到语法错误,迭代器将开始产生无限的错误结果序列并且永远不会继续。您需要确保处理循环内部的错误,否则循环将永远不会结束。在上面的代码片段中,我们通过使用?问号运算符来打破循环并serde_json::Result::Err从我们的函数中返回第一个。

  • 发表此评论只是为了感谢 Jeremy 来到这里,经历了他 8 年前提出的问题的这个版本,并拯救了我的本科生。谢谢杰里米。注意安全 (4认同)