Minimal Object Description Language

MODL (sounds like "doddle") is a compact, plain text data serialisation language for describing objects in as few characters as possible. It's designed to be character efficient when stored or in transport and developer friendly to receive and work with. In this introduction we compare MODL with other data serialisation formats and demonstrate how MODL can store an identical collection of objects using 61% fewer characters than JSON.

Example MODL Object

This is a basic MODL example:

## A pair with the key 'car' is assigned a value containing a map car( ## The map is made up of pairs make=Bentley model=Continental GT ## Comments can be added anywhere styles[ ## A pair with the key 'styles' is assigned a value containing an array, it contains two items fastback convertible ] )
An example MODL object

MODL can be minified by removing comments and using semi-colons to separate pairs and array items (where JSON has commas):

car(make=Bentley;model=Continental GT;styles[fastback;convertible])
An example MODL object minified

Comparison vs JSON & YAML

Let's compare MODL with the two most popular plain text data serialisation languages: JSON and YAML.

Data Type Comparison

We'll compare JSON, YAML and MODL for assigning each data type to the key x. In all cases, we'll use the most character efficient way to assign a value. We'll show a character count (including new line and space characters) and a percentage reduction for YAML and MODL compared to JSON.

String

JSON
"x": "a"
8 chars
YAML
x: a
4 chars(50% less)
MODL
x=a
3 chars(62% less)

Number

JSON
"x":1
5 chars
YAML
x: 1
4 chars(20% less)
MODL
x=1
3 chars(40% less)

Array

JSON
"x":[1,2,3] 
 
 
11 chars
YAML
x:
 - 1
 - 2
 - 3
17 chars(54% more)
MODL
x[1;2;3] 
 
 
8 chars(27% less)

Object / Map

JSON
"x":{"y":"z"} 
13 chars
YAML
x:
 'y': z
10 chars(23% less)
MODL
x(y=z) 
6 chars(53% less)

True

JSON
"x":true
8 chars
YAML
x: y
4 chars(50% less)
MODL
x=01
4 chars(50% less)

False

JSON
"x":false
9 chars
YAML
x: n
4 chars(55% less)
MODL
x=00
4 chars(55% less)

Null

JSON
"x":null
8 chars
YAML
x:
2 chars(75% less)
MODL
x=000
5 chars(37% less)

Single Object Comparison

To compare the three formats for storing a simple object, we'll use the example object from json.org Content on another site.. YAML is the only format with a requirement for spacing, but for comparison each is formatted with 2 space indenting and no extra spacing.

glossary( title=example glossary GlossDiv( title=S GlossList( GlossEntry( ID=SGML SortAs=SGML GlossTerm=Standard Generalized Markup Language Acronym=SGML Abbrev=ISO 8879\:1986 GlossDef( para=A meta-markup language, used to create markup languages such as DocBook. GlossSeeAlso[GML;XML] ) GlossSee=markup ) ) ) )
  • JSON (535 chars)
  • YAML (431 chars)
  • MODL (425 chars)

Reduce Repeating Data

One way to make an object more efficient is to reduce the repetition of data. JSON has no facility to do this but YAML can repeat nodes. MODL deals with repeating data with object referencing and the object index. For illustration, we've highlighted the parts that deal with repeating data in YAML and MODL:

?=SGML:language glossary( title=example glossary GlossDiv( title=S GlossList( GlossEntry( ID=%0 SortAs=%0 GlossTerm=Standard Generalized Markup %1.i Acronym=%0 Abbrev=ISO 8879\:1986 GlossDef( para=A meta-markup %1, used to create markup %1s such as DocBook. GlossSeeAlso[GML;XML] ) GlossSee=markup ) ) ) )
  • JSON (535 chars)
  • YAML (430 chars)
  • MODL (419 chars)

In the MODL object above you will notice percent prefixed numbers %0 and %1, these represent references to the object index. The object index is defined on the first line with the key ?. You may also notice the reference %1.i this instructs the interpreter to run the method i on the second object in the index.

The character efficiency gains in this example are negligible but reducing repeating data can clearly help make larger objects more character efficient.

Minification

It's common practice to minify objects. There are two steps in minification – reducing keys and removing spaces. We've replaced the original keys with 1 or 2 character alternatives and removed all spacing from the JSON and MODL examples. YAML requires spacing for structure so it can't be fully minified:

?=SGML:language;g(t=example glossary;d(t=S;l(e(i=%0;s=%0;gt=Standard Generalized Markup %1.i;a=%0;ab=ISO 8879\:1986;gd(p=A meta-markup %1, used to create markup %1s such as DocBook.;sa=[GML;XML]);gs=markup))))
  • JSON (273 chars)
  • YAML (353 chars)
  • MODL (209 chars)

We've had to make significant sacrifices in readability to achieve these character savings. This makes our object difficult for developers to work with. MODL interpreters can automatically unpack this data, returning it to it's original developer friendly state using classes, which we'll come to in a moment.

As a data serialisation format for storing a single object, we've demonstrated that MODL is more character efficient than JSON and YAML – in this example we've seen a 23% reduction when compared to JSON and over 50% reduction compared to YAML.

Storing a Single Object

JSON
273 chars
YAML
392 chars(43% more)
MODL
209 chars(23% less)

Multiple Object Comparison

MODL offers even more efficiency when describing multiple objects of the same type. Using our previous example as inspiration, we'll describe the three languages that we've been comparing: JSON, YAML and MODL. First of all, we'll compare them without using MODL's class functionality:

[ language( name=JSON full_name=JavaScript Object Notation launch_year=2001 requires_spacing=false spec_url="/www.json.org" structures=[object;array] primitives=[string;number;boolean;"null"] ) language( name=YAML full_name=YAML Ain't Markup Language launch_year=2001 requires_spacing=true spec_url="/www.yaml.org" structures=[mappings;sequences] primitives=[string;number;date;boolean;"null"] ) language( name=MODL full_name=Minimal Object Description Language launch_year=2018 requires_spacing=false spec_url="/www.modl.uk" structures=[pair;map;array;conditional] primitives=[string;number;boolean;"null"] ) ]
  • JSON (938 chars)
  • YAML (845 chars)
  • MODL (728 chars)

Classes

MODL classes allow us to define an object type, which an interpreter will use for all instances of it. Here's a class for our language object:

*class( *id=l *name=language *superclass=map *assign=[ [name;full_name;launch_year;requires_spacing;spec_url;structures;primitives] ] )
A MODL class

In MODL, asterisk prefixed keys provide instructions to the interpreter and never appear in the output object. In the class above, we're instructing the interpreter to create a new class with the id=l and name=language. We're telling it that this class is a child of the map class. We're also telling it how to assign values that are passed to it by multi-value pairs. Now we can describe our languages like this:

*class( *id=l *name=language *superclass=map *assign=[ [name;full_name;launch_year;requires_spacing;spec_url;structures;primitives] ] ) [ l=JSON:JavaScript Object Notation:2001:false:"/www.json.org":[object;array]:[string;number;boolean;"null"] l=YAML:YAML Ain't Markup Language:2001:true:"/www.yaml.org":[mappings;sequences]:[string;number;date;boolean;"null"] l=MODL:Minimal Object Description Language:2018:false:"/www.modl.uk":[pair;map;array;conditional]:[string;number;boolean;"null"] ]
Describing our objects using MODL classes
Minifying Classes

Classes can be minified too. Interpreters recognise *c as well *class, *i as well as *id, *n as well as *name, *s as well as *superclass and *a as well as *assign. Here is our class minified:

*c(*i=l;*n=language;*s=map;*a=[[name;full_name;launch_year;requires_spacing;spec_url;structures;primitives]])
A MODL class minified
Importing a Class File

We've seen how to instruct the interpreter to create a class, we can also instruct the interpreter to import another MODL file using the key *IMPORT or *I. MODL imports can be used for any MODL file. In this example, we're defining our classes in a separate file so we can easily re-use them. We'll call our file c.modl, we can import it simply using *I=c since the interpreter automatically uses the .modl extension if one hasn't been provided.

Let's compare the JSON and YAML minified objects with MODL using an imported class and object referencing to reduce repetition of data:

*I=c;?=object:array:string:number:boolean:language;[l=JSON:JavaScript %0.i Notation:2001:false:"/www.json.org":[%0;%1]:[%2;%3;%4;"null"];l=YAML:YAML Ain't Markup %5.i:2001:true:"/www.yaml.org":[mappings;sequences]:[%2;%3;date;%4;"null"];l=MODL:Minimal %0.i Description %5.i:2018:false:"/www.modl.uk":[[pair;map;%1;conditional]:[%2;%3;%4;"null"]]
  • JSON (530 chars)
  • YAML (629 chars)
  • MODL (364 chars)

Storing Multiple Objects

JSON
530 chars
YAML
629 chars(18% more)
MODL
364 chars(31% less)

Minified and Developer Friendly

In the section above, we looked at how classes can make objects more efficient, they also make output developer friendly. MODL interpreters can output unpacked MODL (pretty printed with original keys) but can also output JSON. To round up, let's look at an input object and an output object.

MODL Input

As we saw above, the MODL input to describe our three languages is 364 characters with an imported MODL class file. It's 468 characters to include the class definition in the file itself. Here it is using the import:

*I=c;?=object:array:string:number:boolean:language;[l=JSON:JavaScript %0.i Notation:2001:false:"/www.json.org":[%0;%1]:[%2;%3;%4;"null"];l=YAML:YAML Ain't Markup %5.i:2001:true:"/www.yaml.org":[mappings;sequences]:[%2;%3;date;%4;"null"];l=MODL:Minimal %0.i Description %5.i:2018:false:"/www.modl.uk":[[pair;map;%1;conditional]:[%2;%3;%4;"null"]]
MODL Input (364 characters)

MODL / JSON Output

After being processed by the MODL interpreter, the output object is unpacked and developer friendly.

[ language( name=JSON full_name=JavaScript Object Notation launch_year=2001 requires_spacing=false spec_url="/www.json.org" structures=[object;array] primitives=[string;number;boolean;"null"] ) language( name=YAML full_name=YAML Ain't Markup Language launch_year=2001 requires_spacing=true spec_url="/www.yaml.org" structures=[mappings;sequences] primitives=[string;number;date;boolean;"null"] ) language( name=MODL full_name=Minimal Object Description Language launch_year=2018 requires_spacing=false spec_url="/www.modl.uk" structures=[pair;map;array;conditional] primitives=[string;number;boolean;"null"] ) ]
  • JSON (938 chars)
  • MODL (728 chars)

Developer Friendly Objects

JSON
938 chars
YAML
845 chars(9% less)
MODL
364 chars(61% less)

Added Functionality

MODL offers extra functionality that typical data serialisation formats don't, including the ability to describe an object conditionally. For detailed information about how MODL works, read the Technical Specification. To get started on your own project take a look at the Developer Libraries.