Everybody seems to be creating serialization formats, so here's mine: Mark's Object FOrmat
JSON is fairly lightweight, but it's still cruftier than it needs to be and doesn't handle dates or some other really useful bits properly. MOFO reduces the cruft and does additional useful stuff (dates, binaries, typed nulls and arrays, binary representation... and comments).
I didn't do CS or anything like that, so I don't know BNF; therefore, the following will be in English.
MIME type: application/mofo
Six basic primitive data types are supported: String, Number, Date, Boolean, Binary and UUID:
- String elements are surrounded by
$
, as in$MOFO is awesome$
.- An actual $ symbol in a string is escaped with a backslash, as in
$Total: \$599.99$
- Standard special string characters are represented as usual:
\n
,\t
, etc - Actual backslashes are represented by a double backslash
\\
- An empty string is represented by
$$
- A null string is represented by
$\0$
(but empty strings are better)
- An actual $ symbol in a string is escaped with a backslash, as in
- Number elements are surrounded by
#
, as in#42#
- A null number is represented by
##
- More explicit number types can be expressed within the delimiters using suffixes:
- 16-bit integer:
1024s
- 32-bit integer:
1024
- 64-bit integer:
1024l
- Single float:
1024.0f
- Double float:
1024.0
- To express constraints, see BADASSERY below
- 16-bit integer:
- Octal and hex formatting can be denoted using prefixes:
- Leading zero for octal:
02000
- Leading
0x
for hex:0x400
- Leading zero for octal:
- A null number is represented by
- Date/time values are surrounded by
/
and are in ISO 8601, as in/2013-08-11T15:17:10Z/
- A null date is represented by
//
- To specify a Time omit the date part of the expression, as in
/15:00:00Z/
- A null date is represented by
- Boolean values are not delimited; they are represented by the single characters
^
for true and!
for false- A null boolean is represented by a
?
- A null boolean is represented by a
- Binary data is represented by non-delimited, lowercase hexadecimal digit pairs surrounded by ampersands, as in
&4d4f464f&
.- A null binary value is represented by
&&
- A null binary value is represented by
- UUIDs are surrounded by
=
, as in=01234567-0123-4567-89ab-0123456789ab=
- A null UUID is represented by
==
- A null UUID is represented by
If it ain't broke, don't fix it.
- Object graphs are surrounded by
{
and}
. - Any text outside the delimiters used for primitive types and the three boolean symbols is considered to be a property name.
- Property names may not contain the following characters:
$
#
/
^
!
?
&
{
}
[
]
- But they can contain spaces
- Property names may not contain the following characters:
Example:
{First name$Douglas$Last name$Adams$Date of birth/1952-03-11/}
The shape of an object graph can be expressed using Brian's Awesomely Descriptive And Short Schema for MOFO (suggested by Brian Kardell):
{First name$Last name$Date of birth/}
To specify a boolean in a schema, use the ?
null signifier.
To indicate that a property may be of any type, use *
.
To include a BADASS declaration within a MOFO object, enclose it in parentheses ()
Example:
{Class$Person$Schema({First name$Last name$Date of birth/Address{House$Street$City$Region$Postcode$Country$}})}
- Lists are surrounded by [ and ]
- Elements within lists are naturally delimited
- Consecutive elements of the same type are split by a single instance of that type's delimiter (or in the case of objects and arrays, their pairs)
Examples:
- Numbers:
[#0#1#1#2#3#5#8#13#21#]
- Strings:
[$Alice$Bob$Charlie$$Eve$]
(The$$
represents a null element) - Dates:
[/1970-01-01/1601-01-01/]
- Booleans:
[^^^!!?^!]
- Objects:
[{color$blue}{color$red}]
- Arrays:
[[#4#2]][[#6$x#7]]
- Mixed (string, string, number, boolean, date, null string):
[$Alice$Bob$#42#^/1752-09-14/$$]
Whitespace outside the $
string delimiters and not within a property name is ignored.
This JSON:
{
"Name": "Phoenix",
"Chassis": "Titan V",
"Drive": "Warp",
"First launch": "5th April 2063",
"Thumbnail": ???,
"Real": false,
"Crew": [ "Cochrane", "Riker", "La Forge" ]
}
Is equivalent to this MOFO:
{Name$Phoenix$Chassis$Titan V$Drive$Warp$First launch/2063-04-05/Real!Thumbnail&94a2f19094213a6f8241a9408266f957&Crew[$Cochrane$Riker$La Forge$]}
Which, since whitespace is insignificant, could also be formatted thusly:
{
Name $Phoenix$
Chassis $Titan V$
Drive $Warp$
First launch /2063-04-05/
Real !
Thumbnail &94a2f19094213a6f8241a9408266f957&
Crew [$Cochrane$Riker$La Forge$]
©©
And it can have comments...
Comments: Do you speak it MOFO?
Yes, yes I do.
©©
}
BADASS/MOFO Schema:
{Name$Chassis$Drive$First launch/Real?Thumbnail&Crew[$]}
If basic BADASS just isn't enough, there is additional "Extra Really Yieldless" syntax which might be useful for code generators, basic data validation descriptions for explaining your service, generating empty records and other such non-sense...
BADASSERY, if it is applied, is done so via trailing <
annotations >
.
Annotations are generally range expressions in which either side may be unspecified, type clarity or enumerations:
- For numbers this can include:
- the type - as in
{calories#<u>}
which means that I may take in from 0 up to an unsigned long's worth of calories. - a range as in in which either number can be unbound and the first may include a type...
{age<21:100>}
means a value between 21 and 100 (drinking age in the US).
- the type - as in
- For strings, this can contain:
- a ranged length - as in
firstName$<1:32>
(a requied string less than 32 characters) - an enumeration of comma separated values, as in
MOFO$<Merely Awesome,The Awesomest>
- a ranged length - as in
- For dates this can include a range of short dates, as in
birthday/<:2000-1-1>
(any date before Jan 1, 2000). - For arrays this indicates specified size.
{top picks[$]<0:10>}
signals an array of strings containing up to 10 elements. - For objects you can express basic variances by simply comma separating descriptions
{favorites[{}<{food$picture&},{song$band$},{movie$actors[$]}>]}
- For binary this is the size in MB, it is generally only useful in describing its max size, for example, 500k: {picture&<0:0.5>}
Any type annotation indicates that a value is not nullable, unless ONLY the the left value is unbounded. Thus, {age#}
is nullable, as is {age#<:99>}
, but {age#<0:99>}
is not.
Best. Wire format. Ever.