Как я могу лениво читать несколько значений JSON из файла / потока в Rust? - PullRequest
0 голосов
/ 22 апреля 2019

Я бы хотел прочитать несколько объектов JSON из файла / программы чтения в Rust, по одному за раз. К сожалению, serde_json::from_reader(...) просто читает до конца файла; кажется, нет никакого способа использовать его для чтения одного объекта или ленивого перебора объектов.

Есть ли способ сделать это? Использование serde_json было бы идеальным, но если бы была другая библиотека, я бы хотел использовать это вместо.

В данный момент я помещаю каждый объект в отдельную строку и анализирую их по отдельности, но я бы действительно предпочел не делать этого.

Пример использования

main.rs

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

in.txt

{"foo": ["bar", "baz"]} 1 2 [] 4 5 6

пример сеанса

Got Object({"foo": Array([String("bar"), String("baz")])})
Got Number(1)
Got Number(2)
Got Array([])
Got Number(4)
Got Number(5)
Got Number(6)

1 Ответ

0 голосов
/ 22 апреля 2019

Это было больно, когда Я хотел сделать это на Python , но, к счастью, в Rust это напрямую поддерживаемая де-факто стандартная serde_json корзина! Он не представлен как простая вспомогательная функция, но нам просто нужно создать a serde_json::Deserializer чтение из нашего файла / ридера, а затем использовать его метод .into_iter(), чтобы получить a StreamDeserializer итератор , выдающий Result s, содержащий serde_json::Value значения JSON.

use serde_json;

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

Следует помнить одну вещь: если встречается синтаксическая ошибка, итератор начнет генерировать бесконечную последовательность результатов ошибок и никогда не будет двигаться дальше. Вам необходимо убедиться, что вы обрабатываете ошибки внутри цикла, иначе цикл никогда не закончится. В приведенном выше фрагменте мы делаем это с помощью оператора вопросительного знака ?, чтобы разорвать цикл и вернуть первый serde_json::Result::Err из нашей функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...