1# μson (uson)
2
3A compact human-readable data serialization format specially designed for shell.
4
5This format is certainly not intended to replace the classical JSON format, but brings different syntax, for use in environments with specific requirements.
6
7Main 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.
8
9This 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).
10
11* [μson Overview](#μson-overview)
12* [Rust Library](#rust-library)
13* [Command-line tool (CLI)](#command-line-tool-cli)
14
15## μson Overview
16
17* [Introduction](#introduction)
18 * [Principles](#principles)
19* [Example](#example)
20* [Basic usage](#basic-usage)
21 * [Standard types](#standard-types)
22 * [Arrays](#arrays)
23 * [Objects](#objects)
24 * [Nested objects](#nested-objects)
25 * [Type casting](#type-casting)
26 * [Custom types](#custom-types)
27 * [Comments](#comments)
28
29### Introduction
30
31#### Principles
32
33* Superset of JSON (every JSON is valid μson).
34* Whitespace is not significant.
35* String quoting `"` is optional.
36* In Array or Object, comma `,` can be replaced by whitespace ` `.
37* Assignment with colon `:` can be repeated to create nested objects (see [Nested objects](#nested-objects)).
38* You can use custom types, casting is done by `!` character (see [Type casting](#type-casting)).
39
40### Example
41
42```
43endpoint:id:wikipedia pages:[Malta Prague "New York"]
44```
45
46Result in JSON:
47```json
48[
49 {
50 "endpoint": {
51 "id": "wikipedia"
52 }
53 },
54 {
55 "pages": [
56 "Malta",
57 "Prague",
58 "New York"
59 ]
60 }
61]
62```
63
64### Basic usage
65
66```
67expr1 expr2 expr3 ..
68```
69
70Supported types:
71* false
72* null
73* true
74* array
75* object
76* number
77* string
78
79#### Standard types
80
81```
82number:12.05 text:Banana quotedText:"John Devilseed" empty:null good:true
83```
84
85Output:
86```json
87[
88 {
89 "number": 12.05
90 },
91 {
92 "text": "Banana"
93 },
94 {
95 "quotedText": "John Devilseed"
96 },
97 {
98 "empty": null
99 },
100 {
101 "good": true
102 }
103]
104```
105
106#### Arrays
107
108```
109simple:[1 2 3] texts:[Malta Budapest "New York"] objects:[{id:1}]
110```
111
112Output:
113```json
114[
115 {
116 "simple": [
117 1,
118 2,
119 3
120 ]
121 },
122 {
123 "texts": [
124 "Malta",
125 "Budapest",
126 "New York"
127 ]
128 },
129 {
130 "objects": [
131 {
132 "id": 1
133 }
134 ]
135 }
136]
137```
138
139#### Objects
140
141```
142obj:{name:John} {nested:[{id:42} value:"Nagano"]}
143```
144
145Output:
146```json
147[
148 {
149 "obj": {
150 "name": "John"
151 }
152 },
153 {
154 "nested": [
155 {
156 "id": 42
157 },
158 {
159 "value": "Nagano"
160 }
161 ]
162 }
163]
164```
165
166#### Nested objects
167
168You can use standard colon notation to expand objects:
169```
170<key>:(<value>|(<key>:(<value>| .. )))
171```
172
173For example:
174```
175cities:eu:hu:budapest:Budapest
176```
177
178becomes:
179```json
180[
181 {
182 "cities": {
183 "eu": {
184 "hu": {
185 "budapest": "Budapest"
186 }
187 }
188 }
189 }
190]
191```
192
193#### Type casting
194
195If you want to return a value in specific type, you can use this syntax:
196```
197<type>!<expr>
198```
199
200For example, this input:
201```
202str!42
203```
204
205produces this output:
206```json
207["42"]
208```
209
210You can use casting repeatedly:
211```
212str!int!12.42
213```
214
215output:
216```json
217["12"]
218```
219
220##### Built-in casting types
221
222**Scalars:**
223* `str` - string
224* `int` - integer
225* `float` - float
226* `null` - null
227* `bool` - boolean
228* `date` - date & time (ISO 8601 formatting)
229
230**Data formats:**
231* `base64` - decode base64 to bytes
232* `hex` - decode hex to bytes
233* `url` - parse URL
234* `regex` - parse regular expression
235* `toml` - parse TOML data
236
237#### Custom types
238
239Custom type support is planned for future versions.
240
241#### Comments
242
243Comments begin with `#` and terminate at end of line.
244
245```
246array:[1 2 3] # this is a comment
247```
248
249Output:
250```json
251[
252 {
253 "array": [
254 1,
255 2,
256 3
257 ]
258 }
259]
260```
261
262## Rust Library
263
264### Installation
265
266Add to your `Cargo.toml`:
267
268```toml
269[dependencies]
270uson = "0.1.0"
271```
272
273### Usage
274
275```rust
276use uson::{parse, Value};
277
278fn main() {
279 // Parse μson
280 let result = parse("name:John age:30 active:true").unwrap();
281
282 // Convert to JSON
283 let json = uson::to_json("name:John age:30", true, true).unwrap();
284 println!("{}", json);
285}
286```
287
288### API
289
290* `uson::parse(input: &str) -> Result<Vec<Value>, ParseError>` - Parse μson string
291* `uson::to_json(input: &str, apply_types: bool, pretty: bool) -> Result<String, ParseError>` - Parse and convert to JSON
292* `uson::stringify(input: &str, apply_types: bool) -> Result<String, ParseError>` - Parse and stringify back to μson
293* `uson::apply_builtin_types(value: Value) -> Value` - Apply built-in type transformations
294
295## Command-line tool (CLI)
296
297### Installation
298
299```bash
300cargo install uson
301```
302
303### Usage
304
305```bash
306$ uson [options] [expression]
307```
308
309### Example
310
311```bash
312$ uson 'user:john age:42'
313```
314
315Returns:
316```json
317[{"user":"john"},{"age":42}]
318```
319
320### Options
321
322For pretty-printed output, use `--pretty` or `-p`:
323
324```bash
325$ uson --pretty 'name:John age:30'
326```
327
328To read from a file, use `--file` or `-f`:
329
330```bash
331$ uson --file input.uson
332```
333
334To apply built-in type transformations, use `--types` or `-t`:
335
336```bash
337$ uson --types 'date!"2024-01-01"'
338```
339
340### Output Formats
341
342- JSON (default): `--json` or `-j`
343- YAML: `--yaml` or `-y` (requires `yaml` feature)
344- Query string: `--form` or `-F` (requires `form` feature)
345
346Example:
347```bash
348$ uson --yaml --pretty 'endpoint:id:wikipedia'
349```
350
351Returns:
352```yaml
353- endpoint:
354 id: wikipedia
355```
356
357### Streams support (pipe)
358
359If you don't specify any input then input is taken from standard input (stdin):
360
361```bash
362$ echo "a b c:[a:42]" | uson --pretty
363```
364
365## Development
366
367```bash
368# Build
369cargo build
370
371# Run tests
372cargo test
373
374# Run compliance tests
375cargo test --test compliance
376
377# Build with all features
378cargo build --all-features
379```
380
381## Inspiration
382
383Inspired by the original JavaScript implementation by [@burningtree](https://github.com/burningtree).
384
385## License
386
387MIT