μ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 parser. This is a port of the original JavaScript implementation.
μson Overview#
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). - You can use custom types, casting is done by
!character (see Type casting).
Example#
endpoint:id:wikipedia pages:[Malta Prague "New York"]
Result in 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:
[
{
"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:
[
{
"simple": [
1,
2,
3
]
},
{
"texts": [
"Malta",
"Budapest",
"New York"
]
},
{
"objects": [
{
"id": 1
}
]
}
]
Objects#
obj:{name:John} {nested:[{id:42} value:"Nagano"]}
Output:
[
{
"obj": {
"name": "John"
}
},
{
"nested": [
{
"id": 42
},
{
"value": "Nagano"
}
]
}
]
Nested objects#
You can use standard colon notation to expand objects:
<key>:(<value>|(<key>:(<value>| .. )))
For example:
cities:eu:hu:budapest:Budapest
becomes:
[
{
"cities": {
"eu": {
"hu": {
"budapest": "Budapest"
}
}
}
}
]
Type casting#
If you want to return a value in specific type, you can use this syntax:
<type>!<expr>
For example, this input:
str!42
produces this output:
["42"]
You can use casting repeatedly:
str!int!12.42
output:
["12"]
Built-in casting types#
Scalars:
str- stringint- integerfloat- floatnull- nullbool- booleandate- date & time (ISO 8601 formatting)
Data formats:
base64- decode base64 to byteshex- decode hex to bytesurl- parse URLregex- parse regular expressiontoml- 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:
[
{
"array": [
1,
2,
3
]
}
]
Rust Library#
Installation#
Add to your Cargo.toml:
[dependencies]
uson = "0.1.0"
Usage#
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<Vec<Value>, ParseError>- Parse μson stringuson::to_json(input: &str, apply_types: bool, pretty: bool) -> Result<String, ParseError>- Parse and convert to JSONuson::stringify(input: &str, apply_types: bool) -> Result<String, ParseError>- Parse and stringify back to μsonuson::apply_builtin_types(value: Value) -> Value- Apply built-in type transformations
Command-line tool (CLI)#
Installation#
cargo install uson
Usage#
$ uson [options] [expression]
Example#
$ uson 'user:john age:42'
Returns:
[{"user":"john"},{"age":42}]
Options#
For pretty-printed output, use --pretty or -p:
$ uson --pretty 'name:John age:30'
To read from a file, use --file or -f:
$ uson --file input.uson
To apply built-in type transformations, use --types or -t:
$ uson --types 'date!"2024-01-01"'
Output Formats#
- JSON (default):
--jsonor-j - YAML:
--yamlor-y(requiresyamlfeature) - Query string:
--formor-F(requiresformfeature)
Example:
$ uson --yaml --pretty 'endpoint:id:wikipedia'
Returns:
- endpoint:
id: wikipedia
Streams support (pipe)#
If you don't specify any input then input is taken from standard input (stdin):
$ echo "a b c:[a:42]" | uson --pretty
Development#
# 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.
License#
MIT