Serde JSON Stream Array Deserializer

Parse large JSON arrays incrementally with serde_json StreamDeserializer, yielding items as they arrive and isolating bad elements.

RustData Integrity

Code

snippet
use serde::Deserialize;
use serde_json::Deserializer;
use std::io::Cursor;

#[derive(Debug, Deserialize)]
struct Reading {
    sensor: String,
    celsius: f32,
}

fn parse_array_items(raw: &str) -> (Vec<Reading>, usize) {
    // 逐元素反序列化:坏元素跳过并计数
    let mut items = Vec::new();
    let mut rejected = 0;

    let mut de = Deserializer::from_str(trim_brackets(raw)).into_iter::<Reading>();
    while let Some(result) = de.next() {
        match result {
            Ok(reading) => items.push(reading),
            Err(_) => rejected += 1,
        }
    }
    (items, rejected)
}

fn trim_brackets(raw: &str) -> &str {
    let trimmed = raw.trim();
    let body = trimmed
        .strip_prefix('[')
        .and_then(|s| s.strip_suffix(']'))
        .unwrap_or(trimmed);
    body
}

fn main() {
    let payload = r#"[
        {"sensor":"hall-1","celsius":21.4},
        {"sensor":"hall-2","celsius":20.9},
        {"sensor":"hall-3","celsius":"not-a-number"},
        {"sensor":"hall-4","celsius":22.1}
    ]"#;

    let (items, rejected) = parse_array_items(payload);
    for reading in &items {
        println!("{} -> {:.1}C", reading.sensor, reading.celsius);
    }
    println!("parsed: {}, rejected: {}", items.len(), rejected);

    // Cursor 演示从 Reader 流式消费同一结构
    let cursor = Cursor::new(trim_brackets(payload).as_bytes().to_vec());
    let stream = Deserializer::from_reader(cursor).into_iter::<Reading>();
    println!("reader-based count: {}", stream.filter_map(|r| r.ok()).count());
}