Low-level JSON library 'Struson' version 0.2.0 released

A few days ago I released version 0.2.0 of my low-level JSON library called 'Struson'. It is still experimental, but any feedback and suggestions regarding API and implementation are welcome!

Compared to version 0.1.0 the new version 0.2.0 adds methods for reading values (JSON strings, numbers and member names) as borrowed strings. This now allows reading JSON data without any additional allocations in many cases.

Examples

  • Reading:

    let json = r#"
        {
            "first": 1.23e4,
            "second": [
                true,
                "value"
            ]
        }
    "#;
    
    let mut json_reader = JsonStreamReader::new(json.as_bytes());
    json_reader.begin_object()?;
    
    assert_eq!(json_reader.next_name()?, "first");
    assert_eq!(json_reader.next_number_as_str()?, "1.23e4");
    
    assert_eq!(json_reader.next_name()?, "second");
    json_reader.begin_array()?;
    assert_eq!(json_reader.next_bool()?, true);
    assert_eq!(json_reader.next_str()?, "value");
    json_reader.end_array()?;
    
    json_reader.end_object()?;
    json_reader.consume_trailing_whitespace()?;
    
  • Writing:

    let mut writer = Vec::<u8>::new();
    let mut json_writer = JsonStreamWriter::new_custom(
        &mut writer,
        WriterSettings {
            pretty_print: true,
            ..Default::default()
        },
    );
    
    json_writer.begin_object()?;
    
    json_writer.name("first")?;
    json_writer.number_value(123)?;
    
    json_writer.name("second")?;
    json_writer.begin_array()?;
    json_writer.bool_value(true)?;
    json_writer.string_value("value")?;
    json_writer.end_array()?;
    
    json_writer.end_object()?;
    json_writer.finish_document()?;
    
    assert_eq!(
        String::from_utf8(writer)?,
        "{\n  \"first\": 123,\n  \"second\": [\n    true,\n    \"value\"\n  ]\n}"
    );
    
  • Seeking and transferring from reader to writer:

    let json = r#"
        {
            "first": 1.23e4,
            "second": [
                true,
                "value"
            ]
        }
    "#;
    
    let mut json_reader = JsonStreamReader::new(json.as_bytes());
    
    let mut writer = Vec::<u8>::new();
    let mut json_writer = JsonStreamWriter::new(&mut writer);
    
    // Skip to path in JSON data, here to JSON string `"value"`
    json_reader.seek_to(&json_path!["second", 1])?;
    
    // Optionally write enclosing data for transferred value
    json_writer.begin_object()?;
    json_writer.name("transferred")?;
    
    json_reader.transfer_to(&mut json_writer)?;
    // Finish reading
    json_reader.skip_to_top_level()?;
    json_reader.consume_trailing_whitespace()?;
    
    json_writer.end_object()?;
    json_writer.finish_document()?;
    
    assert_eq!(String::from_utf8(writer)?, "{\"transferred\":\"value\"}");
    
  • Serde interoperability (requires serde feature):

    let json = r#"
        {
            "outer": {
                "a": 1,
                "b": "value"
            }
        }
    "#;
    
    #[derive(serde::Deserialize, PartialEq, Debug)]
    struct MyStruct {
        a: u32,
        b: String,
    }
    
    let mut json_reader = JsonStreamReader::new(json.as_bytes());
    json_reader.seek_to(&json_path!["outer"])?;
    
    let deserialized: MyStruct = json_reader.deserialize_next()?;
    assert_eq!(
        deserialized,
        MyStruct {
            a: 1,
            b: "value".to_owned()
        }
    );
    
    // Finish reading
    json_reader.skip_to_top_level()?;
    json_reader.consume_trailing_whitespace()?;
    
2 Likes