𓊽 Djed: Djevko Data Format

Djed /dʒɛd/ (Djevko Data Format) is a data format compatible with JSON: the two can be translated into each other.

Djed supports JSON literals which allow embedding JSON documents verbatim as values into Djed.

Djed is more minimal and lightweight than JSON, while being more powerful and flexible at the same time.

Djed is human-friendly and ergonomic.

Like JSON, Djed is suitable for data-interchange (thanks to being efficient to process by machines).

Unlike JSON, Djed is also good for configuration (thanks to its support for comments and ignored entries).

Also unlike JSON, Djed lends itself naturally to streaming (no need for JSON Lines and similar JSON extensions).

The JavaScript library can also handle Infinity and NaN as numbers.

examples

This is a comment

title [djed example]

owner [
  name [tester]
  dob [`2020-08-05T20:30:01+09:00[Asia/Tokyo][u-ca=japanese]`]
]

database [
  enabled [true]
  quoted [`true`]
  ports [
    [8000]
    [8001]
    [8002]
  ]
  data [ [[delta] [phi]] [3.14] ]
  temp targets [ cpu [79.5] case [72.0] ]
]

servers [
  alpha [
    ip [10.0.0.1]
    role [frontend]
  ]
  beta [
    ip [10.0.0.2]
    role [backend]
  ]

  ;discarded key [[with][a][value]]
  ;[discarded section]
]

embedded documents [
  some json [[json]`
  { 
    "id": "b3df0d",
    "count": 55,
    "props": {
      "return code": "59503a7b",
      "status": "pending"
    },
    "associated ids": [
      "3adf7c",
      "ff0df7",
      "3aa670"
    ],
    "parent": null 
  }
  `]
  more json [[json]`55`]
  json string [[json]`"\n\tsomething\u0000"`]
  json array [[json]`[1, 2, 3, 4, null]`]
]
comment
`key` [
  comment
  `value`
]
key2 [
  yaba
  daba
  seq
]
`` [empty]
inf [Infinity]
nan [NaN]
comment c
k`key k`k 
[v`value v`v]

a value

A value starts either at the beginning of a file (the top-level value) or after a [ (a nested value).

A value ends either at the end of a file (the top-level value) or before a ] (a nested value).

whitespace

The following characters are considered whitespace:

' '     (0x20)  space (SPC)
'\t'    (0x09)  horizontal tab (TAB)
'\n'    (0x0a)  newline (LF)
'\v'    (0x0b)  vertical tab (VT)
'\f'    (0x0c)  feed (FF)
'\r'    (0x0d)  carriage return (CR)

comments

Except the last line of a Djed document, all lines outside a quoted string that don’t contain [ ] or `, are treated as comments and ignored:
this is a comment
and so is this
this is not a comment [
this is also not a comment ]
neither is this `

See also ignored entries for an alternative to comments which allows [`].

quoted text

Text surrounded by backticks ` is called quoted text.
`my text`
"my text"
Quoted text can span multiple lines and contain [ or ].
`my text with [brackets]
spanning multiple
lines`
"my text with [brackets]\nspanning multiple\nlines"

Quoted text can also contain ` provided that it is not followed by zero or more whitespace characters and then [ or ], all on the same line.

`invalid quoted text [`]`
error
`more invalid text `  [`
error
If that should be the case, surround the text with '''. Repeat ' as many times as needed for the text to parse correctly:
'`now it's valid [`]`'
"now it's valid [`]"
''`also valid [`]`''
"also valid [`]"
'''`valid as well `  [`'''
"valid as well `  ["
todo: details about heredoc tags, rules; can’t contain , whitespace ignored

Quoted text preceded by any entries other than the [json] entry is an error.

[xml]`error`
error
key [value]
key 2 [value 2]
`error`
error

quoted text as JSON literals

Quoted text preceded by the [json] [entry] is interpreted as a JSON literal. It must contain valid JSON.
[json]`{"key": 123}`
{"key": 123}

quoted text -> JSON strings

Quoted text not preceded by any entries is interpreted as a JSON string.
`text`
"text"
No escape sequences are interpreted inside quoted text.
`\n\r\f\u0000`
"\\n\\r\\f\\u0000"
If escape sequences are necessary, use JSON literals.
[json]`"\n\r\f\u0000"`
"\n\r\f\u0000"

unquoted lines of text

An unquoted line of text may occur at the end of a value.

If it is not empty and is preceded by any entries, it causes an error.

[entry]
error
error
key [value]
error
error
Note that whitespace around an unquoted line is ignored.
    relevant part   

The line here is relevant part, without the surrounding whitespace.

An unquoted line which contains only whitespace is considered empty.

unquoted keywords

An [unquoted line] not preceded by any entries may be a keyword, translated into a specific JSON value.

The keywords are as follows.

keywords true and false -> JSON true and false

The keywords true and false, commonly interpreted as booleans, are translated into their JSON equivalents.
true
true
false
false

keyword null -> JSON null

The keyword null is translated into JSON null.
null
null

keyword seq -> empty JSON array

The keyword seq is translated into an empty JSON array.
seq
[]

keyword map -> empty JSON object

The keyword map is translated into an empty JSON object.
map
{}

numbers

An [unquoted line] not preceded by any entries which conforms to the JavaScript Number grammar is interpreted as a JavaScript number.
123
123

When using Djed directly from JavaScript, Infinity and NaN are translated to proper IEEE754 values.

When translating to JSON, by default they are converted to null, in conformance with semantics of JSON.stringify.

TODO: An option shall be provided to convert Infinty and NaN to strings "Infinity" and "NaN" instead.

entries

There are two kinds of entries: key-value entries and value entries.

Key-value entries look like this:
key [value]
Value entries look like this:
[value]

Concatenating key-value entries and value entries (mixing them together) is an error:

key 1 [value 1] 
[value 2] 
key 2 [value 3]
[value 4]

ignored entries

Entries can be ignored by prefixing them with ;:
;ignored key [ignored value]
;`ignored key` [ignored value]
;[ignored value 2]
These entries are treated as if they weren’t there and can be mixed together with other kinds of entries:
;something [something]
[value 1]
[value 2]
;[something]
key 1 [value 1]
key 2 [value 2]

Ignored entries can be used as multiline documentation comments and to temporarily exclude certain values from being considered (useful for configuration).

Ignored entries can also be used in combination with quoted text as comments which allow [`]:
;[`[ignored]`]
;['`ignored [`]`']

reserved entries

$reserved key [reserved value]
$`reserved key` [reserved value]
$[reserved value 2]

maps -> JSON objects

Key-value entries can be concatenated together to form maps:

key 1 [value 1]
key 2 [value 2]
key 3 [value 3]
{
  "key 1": "value 1",
  "key 2": "value 2",
  "key 3": "value 3",
}
The line breaks are not necessary, so this is equivalent:
key 1 [value 1] key 2 [value 2] key 3 [value 3]

Map keys must be unique, so this is an error:

key 1 [value 1] 
key 1 [error]
error
Whitespace around the keys is ignored, so this is also an error:
  key 1  [value 1]
key 1[value 2]
To include whitespace around a key, it must be quoted with `:
`  key 1  ` [value 1]
{
  "  key 1  ": "value 1"
}
The empty key must be quoted as well:
`` [value of empty key]
{
  "": "value of empty key"
}
Multiline keys also must be quoted:
`multiline
key` [value]
{
  "multiline\nkey": "value"
}
An empty map is introduced by the [keyword] map:
map
{}
key [map]
{
  "key": {}
}

seqs -> JSON arrays

Value entries can be concatenated together to form sequences (seqs for short):
[value 1]
[value 2]
[value 3]
[
  "value 1",
  "value 2",
  "value 3"
]
The line breaks are not necessary, so this is equivalent:
[value 1][value 2][value 3]
Whitespace around the values is ignored, so this is also equivalent:
  [value 1]
[value 2] [value 3]
An empty seq is introduced by the [keyword] seq:
seq
[]
key [seq]
{
  "key": []
}

nesting maps and seqs

Maps and seqs are values, so they can be nested with each other and other values:
key [
  [value 1]
  [value 2]
  [[1][2][3]]
  [
    key 1 [value 1]
    key 2 [value 2]
  ]
]
{
  "key": [
    "value 1",
    "value 2",
    [1, 2, 3],
    {
      "key 1": "value 1",
      "key 2": "value 2"
    }
  ]
}