{"id":20172960,"url":"https://github.com/marcono1234/struson","last_synced_at":"2025-04-04T08:09:13.315Z","repository":{"id":172536394,"uuid":"626041907","full_name":"Marcono1234/struson","owner":"Marcono1234","description":"Streaming JSON reader and writer written in Rust","archived":false,"fork":false,"pushed_at":"2025-03-25T22:49:53.000Z","size":560,"stargazers_count":71,"open_issues_count":14,"forks_count":6,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-25T23:28:58.254Z","etag":null,"topics":["json","json-stream","pull-parser","serde"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/struson","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Marcono1234.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-10T17:12:59.000Z","updated_at":"2025-03-25T22:49:57.000Z","dependencies_parsed_at":"2023-12-16T00:51:30.043Z","dependency_job_id":"c5e39f49-e7a6-4a0a-a6e8-1f316a99571c","html_url":"https://github.com/Marcono1234/struson","commit_stats":null,"previous_names":["marcono1234/struson"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Marcono1234%2Fstruson","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Marcono1234%2Fstruson/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Marcono1234%2Fstruson/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Marcono1234%2Fstruson/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Marcono1234","download_url":"https://codeload.github.com/Marcono1234/struson/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247142070,"owners_count":20890652,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json","json-stream","pull-parser","serde"],"created_at":"2024-11-14T01:32:57.904Z","updated_at":"2025-04-04T08:09:13.275Z","avatar_url":"https://github.com/Marcono1234.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# \u003cdiv align=\"center\"\u003e Struson \u003c/br\u003e [![crates.io](https://img.shields.io/crates/v/struson)](https://crates.io/crates/struson) [![docs.rs](https://img.shields.io/docsrs/struson?label=docs.rs)](https://docs.rs/struson)\u003c/div\u003e\n\nStruson is an [RFC 8259](https://www.rfc-editor.org/rfc/rfc8259.html) compliant streaming JSON reader and writer.\n\nIts main purpose is to allow reading and writing JSON documents in a memory efficient way without having to store the complete JSON document structure in memory.\n\nThe API of Struson was inspired by the streaming API of the Java library [Gson](https://github.com/google/gson) (classes `JsonReader` and `JsonWriter`). It is rather low-level and its methods correspond to the elements of a JSON document, with little abstraction on top of it, allowing to read and write any valid JSON document regardless of its structure or content.\n\n**Note:** This library is still experimental. The performance is not very good yet and the API might be changed in future versions; releases \u003c 1.0.0 might not follow [Semantic Versioning](https://doc.rust-lang.org/cargo/reference/semver.html), breaking changes may occur.\\\nFeedback and suggestions for improvements are welcome!\n\n## Why?\n\nThe most popular JSON Rust crates [Serde JSON (`serde_json`)](https://github.com/serde-rs/json) and [json-rust (`json`)](https://github.com/maciejhirsz/json-rust) mainly provide high level APIs for working with JSON.\n\n- Serde JSON provides an API for converting JSON into DOM like structures (module `serde_json::value`) and object mapper functionality by converting structs to JSON and vice versa. Both requires the complete value to be present in memory. The trait `serde_json::ser::Formatter` actually allows writing JSON in a streaming way, but its API is arguably too low level and inconvenient to use: You have to handle string escaping yourself, and you always have to provide the writer as argument for every method call.\\\n  Note however, that Serde JSON's [`StreamDeserializer`](https://docs.rs/serde_json/latest/serde_json/struct.StreamDeserializer.html) allows reading multiple top-level values in a streaming way, and that certain streaming use cases can be solved with custom `Visitor` implementations, see the documentation for examples of [streaming an array](https://serde.rs/stream-array.html) and [discarding data](https://serde.rs/ignored-any.html).\n\n- json-rust provides an API for converting JSON into DOM like structures (enum `json::JsonValue`), this requires the complete value to be present in memory. The trait `json::codegen::Generator` offers a partial API for writing JSON in a streaming way, however it misses methods for writing JSON arrays and objects in a streaming way.\n\nIf you need to process JSON in a DOM like way or want object mapper functionality to convert structs to JSON and vice versa, then Struson is _not_ suited for your use case and you should instead use one of the libraries above.\n\n## Main features\n\n- Low level streaming API, no implicit value conversion\n- Strong enforcement of correct API usage\n- Panics only for incorrect API usage\\\n  Malformed JSON and unexpected JSON structure only causes errors\n- API does not require recursion for JSON arrays and objects\\\n  Can theoretically read and write arbitrarily deeply nested JSON data\n- Read and write arbitrarily precise JSON numbers as string\\\n  ([`JsonReader::next_number_as_str`](https://docs.rs/struson/latest/struson/reader/trait.JsonReader.html#tymethod.next_number_as_str) and [`JsonWriter::number_value_from_string`](https://docs.rs/struson/latest/struson/writer/trait.JsonWriter.html#tymethod.number_value_from_string))\n- Seek to specific location in JSON data ([`JsonReader::seek_to`](https://docs.rs/struson/latest/struson/reader/trait.JsonReader.html#tymethod.seek_to))\n- Transfer JSON data from a reader to a writer ([`JsonReader::transfer_to`](https://docs.rs/struson/latest/struson/reader/trait.JsonReader.html#tymethod.transfer_to))\n- Read and write arbitrarily large JSON string values\\\n  ([`JsonReader::next_string_reader`](https://docs.rs/struson/latest/struson/reader/trait.JsonReader.html#tymethod.next_string_reader) and [`JsonWriter::string_value_writer`](https://docs.rs/struson/latest/struson/writer/trait.JsonWriter.html#tymethod.string_value_writer))\n- Optional [Serde integration](#serde-integration)\n\n## Usage examples\n\nTwo variants of the API are provided:\n\n- simple: ensures correct API usage at compile-time\n- advanced: ensures correct API usage only at runtime (by panicking); more flexible and\n  provides more functionality\n\n### Simple API\n\n**🔬 Experimental**\\\nThe simple API and its naming is currently experimental, please provide feedback [here](https://github.com/Marcono1234/struson/issues/34).\nIt has to be enabled by specifying the `simple-api` feature in `Cargo.toml`:\n\n```toml\n[dependencies]\nstruson = { version = \"...\", features = [\"simple-api\"] }\n```\n\nAny feedback is appreciated!\n\n#### Reading\n\nSee [`SimpleJsonReader`](https://docs.rs/struson/latest/struson/reader/simple/struct.SimpleJsonReader.html).\n\n```rust\nuse struson::reader::simple::*;\n\n// In this example JSON data comes from a string;\n// normally it would come from a file or a network connection\nlet json_reader = SimpleJsonReader::new(r#\"[\"a\", \"short\", \"example\"]\"#.as_bytes());\nlet mut words = Vec::\u003cString\u003e::new();\njson_reader.read_array_items(|item_reader| {\n    let word = item_reader.read_string()?;\n    words.push(word);\n    Ok(())\n})?;\nassert_eq!(words, vec![\"a\", \"short\", \"example\"]);\n```\n\nFor reading nested values, the methods [`read_seeked`](https://docs.rs/struson/latest/struson/reader/simple/trait.ValueReader.html#tymethod.read_seeked)\nand [`read_seeked_multi`](https://docs.rs/struson/latest/struson/reader/simple/trait.ValueReader.html#tymethod.read_seeked_multi)\ncan be used:\n\n```rust\nuse struson::reader::simple::*;\nuse struson::reader::simple::multi_json_path::multi_json_path;\n\n// In this example JSON data comes from a string;\n// normally it would come from a file or a network connection\nlet json = r#\"{\n    \"users\": [\n        {\"name\": \"John\", \"age\": 32},\n        {\"name\": \"Jane\", \"age\": 41}\n    ]\n}\"#;\nlet json_reader = SimpleJsonReader::new(json.as_bytes());\n\nlet mut ages = Vec::\u003cu32\u003e::new();\n// Select the ages of all users\nlet json_path = multi_json_path![\"users\", [*], \"age\"];\njson_reader.read_seeked_multi(\u0026json_path, false, |value_reader| {\n    let age = value_reader.read_number()??;\n    ages.push(age);\n    Ok(())\n})?;\nassert_eq!(ages, vec![32, 41]);\n```\n\n#### Writing\n\nSee [`SimpleJsonWriter`](https://docs.rs/struson/latest/struson/writer/simple/struct.SimpleJsonWriter.html).\n\n```rust\nuse struson::writer::simple::*;\n\n// In this example JSON bytes are stored in a Vec;\n// normally they would be written to a file or network connection\nlet mut writer = Vec::\u003cu8\u003e::new();\nlet json_writer = SimpleJsonWriter::new(\u0026mut writer);\njson_writer.write_object(|object_writer| {\n    object_writer.write_number_member(\"a\", 1)?;\n    object_writer.write_bool_member(\"b\", true)?;\n    Ok(())\n})?;\n\nlet json = String::from_utf8(writer)?;\nassert_eq!(json, r#\"{\"a\":1,\"b\":true}\"#);\n```\n\n### Advanced API\n\n#### Reading\n\nSee [`JsonStreamReader`](https://docs.rs/struson/latest/struson/reader/struct.JsonStreamReader.html).\n\n```rust\nuse struson::reader::*;\n\n// In this example JSON data comes from a string;\n// normally it would come from a file or a network connection\nlet json = r#\"{\"a\": [1, true]}\"#;\nlet mut json_reader = JsonStreamReader::new(json.as_bytes());\n\njson_reader.begin_object()?;\nassert_eq!(json_reader.next_name()?, \"a\");\n\njson_reader.begin_array()?;\nassert_eq!(json_reader.next_number::\u003cu32\u003e()??, 1);\nassert_eq!(json_reader.next_bool()?, true);\njson_reader.end_array()?;\n\njson_reader.end_object()?;\n// Ensures that there is no trailing data\njson_reader.consume_trailing_whitespace()?;\n```\n\n#### Writing\n\nSee [`JsonStreamWriter`](https://docs.rs/struson/latest/struson/writer/struct.JsonStreamWriter.html).\n\n```rust\nuse struson::writer::*;\n\n// In this example JSON bytes are stored in a Vec;\n// normally they would be written to a file or network connection\nlet mut writer = Vec::\u003cu8\u003e::new();\nlet mut json_writer = JsonStreamWriter::new(\u0026mut writer);\n\njson_writer.begin_object()?;\njson_writer.name(\"a\")?;\n\njson_writer.begin_array()?;\njson_writer.number_value(1)?;\njson_writer.bool_value(true)?;\njson_writer.end_array()?;\n\njson_writer.end_object()?;\n// Ensures that the JSON document is complete and flushes the buffer\njson_writer.finish_document()?;\n\nlet json = String::from_utf8(writer)?;\nassert_eq!(json, r#\"{\"a\":[1,true]}\"#);\n```\n\n## Serde integration\n\nOptional integration with [Serde](https://docs.rs/serde/latest/serde/) exists to allow writing a `Serialize` to a `JsonWriter` and reading a `Deserialize` from a `JsonReader`. See the [`serde` module](https://docs.rs/struson/latest/struson/serde/index.html) of this crate for more information.\n\n## Changelog\n\nSee [GitHub releases](https://github.com/Marcono1234/struson/releases).\n\n## Building\n\nThis project uses [cargo-make](https://github.com/sagiegurari/cargo-make) for building:\n\n```sh\ncargo make\n```\n\nIf you don't want to install cargo-make, you can instead manually run the tasks declared in the [`Makefile.toml`](Makefile.toml).\n\n## Similar projects\n\n- \u003chttps://github.com/alexmaco/json_stream\u003e\n  \u003e A streaming JSON parser/emitter library for rust\n- \u003chttps://github.com/sarum90/qjsonrs\u003e\n  \u003e JSON Tokenizer written in Rust\n- \u003chttps://github.com/jeremiah-shaulov/nop-json\u003e\n  \u003e JSON serialization/deserialization (full-featured, modern, streaming, direct into struct/enum)\n- \u003chttps://github.com/isagalaev/ijson-rust\u003e\n  \u003c!-- Note: Project itself has no README or description --\u003e\n  \u003e Rust re-implementation of the Python streaming JSON parser [ijson](https://github.com/isagalaev/ijson)\n- \u003chttps://github.com/byron/json-tools\u003e\n  \u003e A zero-copy json-lexer, filters and serializer.\n- \u003chttps://github.com/01mf02/hifijson\u003e\n  \u003e High-fidelity JSON lexer and parser\n- \u003chttps://github.com/khonsulabs/justjson\u003e's `justjson::parser::Tokenizer`\n  \u003e A JSON tokenizer, which converts JSON source to a series of Tokens\n- \u003chttps://github.com/iovxw/jsonpull\u003e\n  \u003e Json pull parser\n- \u003chttps://github.com/zotta/json-writer-rs\u003e\n  \u003e Simple and fast crate for writing JSON to a string without creating intermediate objects\n- \u003chttps://crates.io/crates/jsn\u003e\n  \u003e A queryable, streaming, JSON pull-parser with low allocation overhead.\n- \u003chttps://github.com/michel-kraemer/actson-rs\u003e\n  \u003e Actson is a low-level JSON parser for reactive applications and non-blocking I/O.\n- [rustc-serialize `Parser`](https://docs.rs/rustc-serialize/latest/rustc_serialize/json/struct.Parser.html) (deprecated)\n  \u003e A streaming JSON parser implemented as an iterator of JsonEvent, consuming an iterator of char.\n\n## License\n\nLicensed under either of\n\n- [Apache License, Version 2.0](LICENSE-APACHE)\n- [MIT License](LICENSE-MIT)\n\nat your option.\n\nAll contributions you make to this project are licensed implicitly under both licenses mentioned above, without any additional terms or conditions.\n\nNote: This dual-licensing is the same you see for the majority of Rust projects, see also the [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/necessities.html#crate-and-its-dependencies-have-a-permissive-license-c-permissive).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcono1234%2Fstruson","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarcono1234%2Fstruson","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcono1234%2Fstruson/lists"}