SION, a serialization format a little more expressive than JSON
This page introduces and describes SION, a data serialization format that addresses the shortcomings of JSON, arguably the most popular data serialization format today.
Because JSON is not expressive enough
SION is a data serialization format:
- Named after "Swift Interchangeable Object Notation". As JSON is originated from a {ECMA,Java}Script literal, SION is originated from a Swift literal.
- but like JSON, it should not be considered acronym. It is a textual data format of its own and independent of programming languages.
- It can serialize anything JSON can. Plus
- support
Data- binary blobs - support
Date
- support
- non-
Stringkeys inDictionaryIntandDoubledistinctively, notNumber.- Therefore you can exchange 64-bit integers losslessly.
- No
{}needed forDictionary(aka Map, Hash, Object…).[and]delimit bothArrayandDictionary. What makes aDictionaryaDictionaryis:between keys and values, not a different pair of brackets.
Doublecan be expressed both in decimal and C99 Hexadecimal floating-point notation.NaNand ±Infinityare valid.- This is necessary for really interchangeable format. Suppose you want to send calculation results with errors.
- // comment is allowed!.
//up to newline.- The lack of comment support of JSON definitely makes it suck as a configuration file format.
- Roughly equivalent to MsgPack in terms of capability.
- MsgPack is a binary serialization while
SIONis a text serialization.
- MsgPack is a binary serialization while
Below is a table of a few notable serialization formats and capabilities.
| Type | SION | MsgPack | JSON | Property List | Comment |
|---|---|---|---|---|---|
Nil |
✔︎ | ✔︎ | ✔︎ | ❌ | plist: .binary only |
Bool |
✔︎ | ✔︎ | ✔︎ | ✔︎ | |
Int |
✔︎ | ✔︎ | ❌ | ✔︎ | 64bit |
Double |
✔︎ | ✔︎ | ✔︎ | ✔︎ | JSON's Number |
String |
✔︎ | ✔︎ | ✔︎ | ✔︎ | utf-8 encoded |
Data |
✔︎ | ✔︎ | ❌ | ✔︎ | binary blob |
Date |
✔︎ | ✔︎ | ❌ | ✔︎ | .timeIntervalSince1970 in Double |
[Self] |
✔︎ | ✔︎ | ✔︎ | ✔︎ | aka Array |
[String:Self] |
✔︎ | ✔︎ | ✔︎ | ✔︎ | aka Object, Map… |
[Self:Self] |
✔︎ | ✔︎ | ❌ | ❌ | non-String keys |
Ext |
✔︎ | ✔︎ | ❌ | ❌ | msgpack extension |
One bracket to rule them all
Unlike JSON, SION needs no {} for Dictionary (aka Map, Hash, Object…). Both Array and Dictionary are delimited by [ and ]. They are distinguished not by brackets but by what is inside — key : value pairs make it a Dictionary:
[ "zero", "one", "two" ] // an Array [ 0:"zero", 1:"one", 2:"two" ] // a Dictionary [] // an empty Array [:] // an empty Dictionary
This is not just aesthetics:
- Simpler syntax. One kind of bracket for collections means fewer tokens, fewer delimiter-mismatch errors, and a smaller grammar.
- Collections are one concept. A
Dictionaryis just a collection whose elements are keyed —:is what says so. AnArrayis arguably aDictionaryimplicitly keyed by 0, 1, 2… as a matter of fact["zero", "one", "two"]and[0:"zero", 1:"one", 2:"two"]are semantically equivalent. - A natural consequence of non-
Stringkeys. JSON's{}carries the implicit promise that keys are strings. Once any value can be a key, that distinction loses its reason to exist.
The only price is [:], the empty Dictionary, since [] is taken by the empty Array. A fair trade for a whole class of brackets.
Implementations
- Swift
- Go
- ECMAScript (aka JavaScript)
- Rust
- Python 3
- Perl 5
- Raku
Syntax
- ANTLR4(EBNF)
Examples
Below is an example of data encoded in SION.
[ "array": [ nil, true, 1, // Int in decimal 1.0, // Double in decimal "one", [1], ["one" : 1.0] ], "bool": true, "data": .Data("R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"), "date": .Date(0x0p+0), "dictionary": [ "array" : [], "bool" : false, "double" : 0.0, "int" : 0, "nil" : nil, "object" : [:], "string" : "" ], "double": 0x1.518f5c28f5c29p+5, // double in hex "ext": .Ext("1NTU"), // 0xd4,0xd4,0xd4 "int": -42, // Int in decimal "nil": nil, "string": "漢字、カタカナ、ひらがなの入ったstring😇", "url": "https://github.com/dankogai/" ]
As you notice,
- comments are allowed -
//up to newline. - non-
Stringkeys are allowed. Any data conforming to SION can be a {Dictionary,Map,Object} key. - no
{}in sight. The whole document is aDictionary, delimited by[and]like everything else.
And below is an example of JSON-compatible SION…
[ "array" : [ nil, true, 1, // Int in decimal 1.0, // Double in decimal "one", [1], ["one" : 1.0] ], "bool" : true, "dictionary" : [ "array" : [], "bool" : false, "double" : 0.0, "int" : 0, "nil" : nil, "object" : [:], "string" : "" ], "double" : 42.195, "int" : -42, "nil" : nil, "string" : "漢字、カタカナ、ひらがなの入ったstring😇", "url" : "https://github.com/dankogai/" ]
…which turns into a JSON below.
{ "array" : [ null, true, 1, 1.0, "one", [1], {"one": 1.0} ], "bool" : true, "dictionary": { "array": [], "bool": false, "double": 0.0, "int": 0, "nil": null, "object": {}, "string": "" }, "double": 42.195, "int": -42, "nil": null, "string": "漢字、カタカナ、ひらがなの入ったstring😇", "url": "https://github.com/dankogai/" }
Note the {}s are back, along with the comments gone.