# μson (uson) A compact human-readable data serialization format specially designed for shell. This format is certainly not intended to replace the classical JSON format, but brings different syntax, for use in environments with specific requirements. Main advantage should be in better writability (mostly in the command line), because it uses less expressive syntax. The purpose is not to create a format that is as small as possible in terms of byte size. This is a Rust implementation of μson. Grammar is written using [Pest](https://pest.rs/) parser. This is a port of the original [JavaScript implementation](https://github.com/burningtree/uson). * [μson Overview](#μson-overview) * [Rust Library](#rust-library) * [Command-line tool (CLI)](#command-line-tool-cli) ## μson Overview * [Introduction](#introduction) * [Principles](#principles) * [Example](#example) * [Basic usage](#basic-usage) * [Standard types](#standard-types) * [Arrays](#arrays) * [Objects](#objects) * [Nested objects](#nested-objects) * [Type casting](#type-casting) * [Custom types](#custom-types) * [Comments](#comments) ### Introduction #### Principles * Superset of JSON (every JSON is valid μson). * Whitespace is not significant. * String quoting `"` is optional. * In Array or Object, comma `,` can be replaced by whitespace ` `. * Assignment with colon `:` can be repeated to create nested objects (see [Nested objects](#nested-objects)). * You can use custom types, casting is done by `!` character (see [Type casting](#type-casting)). ### Example ``` endpoint:id:wikipedia pages:[Malta Prague "New York"] ``` Result in JSON: ```json [ { "endpoint": { "id": "wikipedia" } }, { "pages": [ "Malta", "Prague", "New York" ] } ] ``` ### Basic usage ``` expr1 expr2 expr3 .. ``` Supported types: * false * null * true * array * object * number * string #### Standard types ``` number:12.05 text:Banana quotedText:"John Devilseed" empty:null good:true ``` Output: ```json [ { "number": 12.05 }, { "text": "Banana" }, { "quotedText": "John Devilseed" }, { "empty": null }, { "good": true } ] ``` #### Arrays ``` simple:[1 2 3] texts:[Malta Budapest "New York"] objects:[{id:1}] ``` Output: ```json [ { "simple": [ 1, 2, 3 ] }, { "texts": [ "Malta", "Budapest", "New York" ] }, { "objects": [ { "id": 1 } ] } ] ``` #### Objects ``` obj:{name:John} {nested:[{id:42} value:"Nagano"]} ``` Output: ```json [ { "obj": { "name": "John" } }, { "nested": [ { "id": 42 }, { "value": "Nagano" } ] } ] ``` #### Nested objects You can use standard colon notation to expand objects: ``` :(|(:(| .. ))) ``` For example: ``` cities:eu:hu:budapest:Budapest ``` becomes: ```json [ { "cities": { "eu": { "hu": { "budapest": "Budapest" } } } } ] ``` #### Type casting If you want to return a value in specific type, you can use this syntax: ``` ! ``` For example, this input: ``` str!42 ``` produces this output: ```json ["42"] ``` You can use casting repeatedly: ``` str!int!12.42 ``` output: ```json ["12"] ``` ##### Built-in casting types **Scalars:** * `str` - string * `int` - integer * `float` - float * `null` - null * `bool` - boolean * `date` - date & time (ISO 8601 formatting) **Data formats:** * `base64` - decode base64 to bytes * `hex` - decode hex to bytes * `url` - parse URL * `regex` - parse regular expression * `toml` - parse TOML data #### Custom types Custom type support is planned for future versions. #### Comments Comments begin with `#` and terminate at end of line. ``` array:[1 2 3] # this is a comment ``` Output: ```json [ { "array": [ 1, 2, 3 ] } ] ``` ## Rust Library ### Installation Add to your `Cargo.toml`: ```toml [dependencies] uson = "0.1.0" ``` ### Usage ```rust use uson::{parse, Value}; fn main() { // Parse μson let result = parse("name:John age:30 active:true").unwrap(); // Convert to JSON let json = uson::to_json("name:John age:30", true, true).unwrap(); println!("{}", json); } ``` ### API * `uson::parse(input: &str) -> Result, ParseError>` - Parse μson string * `uson::to_json(input: &str, apply_types: bool, pretty: bool) -> Result` - Parse and convert to JSON * `uson::stringify(input: &str, apply_types: bool) -> Result` - Parse and stringify back to μson * `uson::apply_builtin_types(value: Value) -> Value` - Apply built-in type transformations ## Command-line tool (CLI) ### Installation ```bash cargo install uson ``` ### Usage ```bash $ uson [options] [expression] ``` ### Example ```bash $ uson 'user:john age:42' ``` Returns: ```json [{"user":"john"},{"age":42}] ``` ### Options For pretty-printed output, use `--pretty` or `-p`: ```bash $ uson --pretty 'name:John age:30' ``` To read from a file, use `--file` or `-f`: ```bash $ uson --file input.uson ``` To apply built-in type transformations, use `--types` or `-t`: ```bash $ uson --types 'date!"2024-01-01"' ``` ### Output Formats - JSON (default): `--json` or `-j` - YAML: `--yaml` or `-y` (requires `yaml` feature) - Query string: `--form` or `-F` (requires `form` feature) Example: ```bash $ uson --yaml --pretty 'endpoint:id:wikipedia' ``` Returns: ```yaml - endpoint: id: wikipedia ``` ### Streams support (pipe) If you don't specify any input then input is taken from standard input (stdin): ```bash $ echo "a b c:[a:42]" | uson --pretty ``` ## Development ```bash # Build cargo build # Run tests cargo test # Run compliance tests cargo test --test compliance # Build with all features cargo build --all-features ``` ## Inspiration Inspired by the original JavaScript implementation by [@burningtree](https://github.com/burningtree). ## License MIT