Serde: Streaming serialize and deserialize packets

Created on 1 Dec 2017  路  3Comments  路  Source: serde-rs/serde

From IRC:

I have some multimedia format I want to write down in a sort of readable form, so I have some global information that can fit a json itself and then for each packet/frame I'd have 1 json each
initially I wanted to assemble the array of packets/frames as they come but looks not so plausible
so I'd just concatenate the multiple json (and that works)
but then I couldn't find a way to tell serde on the deserializing side that's ok to have trailing data

support

All 3 comments

Streaming serialization and deserialization of concatenated JSON objects

#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct Index {
    len: usize,
    name: String,
}

#[derive(Serialize, Deserialize, Debug)]
struct Packet {
    name: String,
    data: Vec<u8>,
}

fn main() {
    try_main().unwrap();
}

fn try_main() -> Result<(), serde_json::Error> {
    let mut out = Vec::new();

    {
        let mut ser = serde_json::Serializer::new(&mut out);
        let npackets = 4;
        Index { len: npackets, name: "index".to_owned() }.serialize(&mut ser)?;
        for i in 0..npackets {
            Packet { name: "packet".to_owned(), data: vec![i as u8] }.serialize(&mut ser)?;
        }
    }

    println!("{}", String::from_utf8_lossy(&out));

    {
        let mut de = serde_json::Deserializer::from_slice(&out);
        let index = Index::deserialize(&mut de)?;
        println!("{:?}", index);
        for _ in 0..index.len {
            let packet = Packet::deserialize(&mut de)?;
            println!("{:?}", packet);
        }
    }

    Ok(())
}

Streaming serialization and deserialization of a single top-level array

#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;

use serde::ser::{Serializer, SerializeSeq};
use serde::de::{self, Deserializer, Visitor, SeqAccess};

use std::fmt;
use std::io::{self, Write};

#[derive(Serialize, Deserialize, Debug)]
struct Index {
    len: usize,
    name: String,
}

#[derive(Serialize, Deserialize, Debug)]
struct Packet {
    name: String,
    data: Vec<u8>,
}

fn main() {
    try_main().unwrap();
}

fn try_main() -> Result<(), serde_json::Error> {
    let mut out = Vec::new();

    {
        let mut ser = serde_json::Serializer::pretty(&mut out);
        let npackets = 4;
        let mut seq = ser.serialize_seq(Some(1 + npackets as usize))?; // or None if unknown
        seq.serialize_element(&Index { len: npackets, name: "index".to_owned() })?;
        for i in 0..npackets {
            seq.serialize_element(&Packet { name: "packet".to_owned(), data: vec![i as u8] })?;
        }
        seq.end()?;
    }

    println!("{}", String::from_utf8_lossy(&out));

    {
        let mut de = serde_json::Deserializer::from_slice(&out);
        let action = DebugPackets { out: io::stdout() };
        de.deserialize_seq(action)?;
    }

    Ok(())
}

struct DebugPackets<W> {
    out: W,
}

impl<'de, W> Visitor<'de> for DebugPackets<W>
    where W: Write
{
    type Value = ();

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("array of index + packets")
    }

    fn visit_seq<A>(mut self, mut seq: A) -> Result<Self::Value, A::Error>
        where A: SeqAccess<'de>
    {
        let index = match seq.next_element::<Index>()? {
            Some(index) => index,
            None => {
                return Err(de::Error::custom("index was missing"));
            }
        };
        let _ = writeln!(self.out, "{:?}", index);

        for _ in 0..index.len {
            match seq.next_element::<Packet>()? {
                Some(packet) => {
                    let _ = writeln!(self.out, "{:?}", packet);
                }
                None => {
                    return Err(de::Error::custom("fewer packets than expected"));
                }
            }
        }

        Ok(())
    }
}

Same with string and without index:

#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;

use serde::de::{self, Deserializer, SeqAccess, Visitor};

use std::fmt;
use std::io::{self, Write};

#[derive(Serialize, Deserialize, Debug)]
struct Packet {
    name: String,
    data: Vec<u8>,
}

fn main() -> std::io::Result<()> {
    let out = r#"
[
  {
    "name": "packet",
    "data": [
      0
    ]
  },
  {
    "name": "packet",
    "data": [
      1
    ]
  },
  {
    "name": "packet",
    "data": [
      2
    ]
  },
  {
    "name": "packet",
    "data": [
      3
    ]
  }
]
"#;

    {
        let mut de = serde_json::Deserializer::from_str(&out);
        let action = DebugPackets { out: io::stdout() };
        de.deserialize_seq(action)?;
    }

    Ok(())
}

struct DebugPackets<W> {
    out: W,
}

impl<'de, W> Visitor<'de> for DebugPackets<W>
where
    W: Write,
{
    type Value = ();

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("array of packets")
    }

    fn visit_seq<A>(mut self, mut seq: A) -> Result<Self::Value, A::Error>
    where
        A: SeqAccess<'de>,
    {
        while let Some(packet) = seq.next_element::<Packet>()? {
            let _ = writeln!(self.out, "{:?}", packet);
        }
        Ok(())
    }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

kleimkuhler picture kleimkuhler  路  3Comments

Boscop picture Boscop  路  4Comments

sackery picture sackery  路  3Comments

dtolnay picture dtolnay  路  4Comments

swfsql picture swfsql  路  3Comments