JONF icon

JONF

Json for cONF

Quick example

# Fictional supercomputer IaC

name - Deep Thought
answer - 42

hardware =
  cores = 42
  eyes =
    left - green
    right - violet

about -
  indented, unquoted,
  and raw - \no special chars

  multiline string here

pets =
  - cat
  - dog
  - turtle  # or tortoise

friends =
  =
    name - Alice
    age = null
  =
    name - Bob
    age = 42

scripts =
  check -
    set -eu  # No more && chains
    DIRS="src tests"
    lint $DIRS
    test $DIRS

Equal JSON:

{
  "name": "Deep Thought",
  "answer": "42",
  "hardware": {
    "cores": 42,
    "eyes": {
      "left": "green",
      "right": "violet"
    }
  },
  "about": "indented, unquoted,\nand raw - \\no special chars\n\nmultiline string here",
  "pets": [
    "cat",
    "dog",
    "turtle"
  ],
  "friends": [
    {
      "name": "Alice",
      "age": null
    },
    {
      "name": "Bob",
      "age": 42
    }
  ],
  "scripts": {
    "check": "set -eu\nDIRS=\"src tests\"\nlint $DIRS\ntest $DIRS"
  }
}

Goals

Motivation

JSON is great for API, but not as great for config files and DSLs, that’s why alternatives are trying to fill the gap:

  1. ELDF
  2. ENO
  3. HCL
  4. HJSON
  5. HOCON
  6. HRON
  7. ION
  8. JSON5
  9. Jsonnet
  10. NestedText
  11. SDLang
  12. StrictYAML
  13. TOML
  14. YAML
    xkcd: Standards
  15. JONF

Cheatsheet

Key-value separators and array markers:

Bash memo:

Rules

JONF in 10 examples

1. Root value

One-line non-indented JSON value is a valid JONF root value, because in a one-line case, JSON is great:

{"some": "object", "key": "value"}

["some", "array", "here"]

"some string"

-3.14

true

false

null

JONF object, JONF array, JONF indented unquoted multiline string - are valid root values too, e.g:

  indented unquoted
  multiline

  string

Equal JSON:

"indented unquoted\nmultiline\n\nstring"

More features of unquoted string are explained in the next examples

2. JONF array

- Alice in Wonderland
-
  multiline
  string

  here

= "multiline\nstring\n\nhere"
= "  explici\t whitespace \n"
- unquoted is raw - \no special chars"
- great for regex: [\n\r\t]+
- 42
= 42
- -3.14
= -3.14
- true
= true
- false
= false
- null
= null
- []
= []
- {}
= {}
- ""
= ""

Equal JSON:

[
  "Alice in Wonderland",
  "multiline\nstring\n\nhere",
  "multiline\nstring\n\nhere",
  "  explici\t whitespace \n",
  "unquoted is raw - \\no special chars\"",
  "great for regex: [\\n\\r\\t]+",
  "42",
  42,
  "-3.14",
  -3.14,
  "true",
  true,
  "false",
  false,
  "null",
  null,
  "[]",
  [],
  "{}",
  {},
  "\"\"",
  ""
]

3. JONF object

name - Deep Thought
answer - 42
cores = 42
"some - strange = key" - value
42 - keys are always strings
true = "even with =, it affects values only"

Equal JSON:

{
  "name": "Deep Thought",
  "answer": "42",
  "cores": 42,
  "some - strange = key": "value",
  "42": "keys are always strings",
  "true": "even with =, it affects values only"
}

4. Object in object

type - dragon
eyes =
  left - green
  right - violet

Equal JSON:

{
  "type": "dragon",
  "eyes": {
    "left": "green",
    "right": "violet"
  }
}

5. Object in array

=
  name - Alice
  age = null
=
  name - Bob
  age = 42

Equal JSON:

[
  {
    "name": "Alice",
    "age": null
  },
  {
    "name": "Bob",
    "age": 42
  }
]

Please note = should be used as an array marker, unless you want unquoted strings:

- unquoted string
-
  multiline - unquoted
  string = here

Equal JSON:

[
  "unquoted string",
  "multiline - unquoted\nstring = here"
]

6. Depth and boundaries

JONF is arguably more readable than YAML below, let alone YAML’s typing flaw:

person:
  name: abcd
  nick: efgh
friends:
- name: hijk
  nick: lmno
- name: pqrs
  nick: tuvw

It looks like all names here are on the same depth in YAML, which is misleading, and it takes some effort to notice the boundaries of each friend

JONF shows the depth and boundaries correctly, improving readability:

person =
  name - abcd
  nick - efgh
friends =
  =
    name - hijk
    nick - lmno
  =
    name - pqrs
    nick - tuvw

7. Array in object

name - Bob
kids =
  - Charlie
  - Dave
  - Eve

Equal JSON:

{
  "name": "Bob",
  "kids": [
    "Charlie",
    "Dave",
    "Eve"
  ]
}

8. Array in array

=
  - We
  - are
=
  - almost
  =
    - done!

Equal JSON:

[
  [
    "We",
    "are"
  ], [
    "almost",
    [
      "done!"
    ]
  ]
]

JONF is obviously better than JSON in a multi-line case

Again, JSON is the best for one-liners, that’s why they are valid in JONF:

[["We", "are"], ["almost", ["done!"]]]

9. Comment

Text from # to the end of line is a comment if # is the first character in the line or there is a whitespace before it and it is not inside of JSON value:

# Full-line comment
name - Alice  # Inline comment
url - https://example.org/#alice
location = "Wonderland # 42"

Equal JSON:

{
  "name": "Alice",
  "url": "https://example.org/#alice",
  "location": "Wonderland # 42",
}

JONF uses # and never // or /* */ for the same reason JSON uses double-quotes and never single-quotes: to keep it simple

10. DSL

In serverless.jonf variables are parsed after JONF is parsed:

custom =
  debug = true
  verbose - ${self:custom.debug}

Equal JSON:

{
  "custom": {
    "debug": true,
    "verbose": "${self:custom.debug}"
  }
}

Equal JSON, parsed by DSL:

{
  "custom": {
    "debug": true,
    "verbose": true
  }
}

Note that DSL decided to change type of verbose to the type of the variable it referenced. JONF never does that, it is just a container format, strictly mapped to JSON only

Roadmap

JONF as JONF

Name - JONF
Version - 0.0.17
Filename extension - .jonf
Internet media type - application/jonf  # TODO
Website - jonf.app
Email - support@jonf.app
Maintainer - whyolet.com
License - MIT
Open format? - Yes
Type of format - Data interchange
Extended from - JSON

That’s all!

Simple and valuable, right?

Thank you for reading

Please post an issue or idea or contribute otherwise:

GitHub icon https://github.com/whyolet/jonf