Specification

Introduction

JSONA = JSON + Annotation. JSON describes the data, Annotation describes the logic.

Example

The examples below cover all the features of JSONA.

/*
 multiple line comment
*/

// single line comment

{
    @null /* abc */ @nullVerbose(null)
    @bool(true) // single line comment
    @float(3.14)
    @number(-3)
    @string('abc "def" ghi')
    @array([3,4])
    @object({
        k1: "v1",
        k2: "v2",
    })

    nullValue: /* xyz */ null,
    boolTrue: true,
    boolFalse: false,
    float: 3.14,
    floatNegative: -3.14,
    floatNegativeWithoutInteger: -.14,
    floatNegativeWithoutDecimal: -3.,
    integer: 3,
    hex: 0x1a,
    binary: 0b01,
    octal: 0o12,
    integerNegative: -3,
    stringSingleQuota: 'abc "def" ghi',
    stringDoubleQuota: "abc 'def' ghi",
    stringBacktick: `abc
def \`
xyz`,
    stringEscape1: '\0\b\f\n\r\t\u000b\'\\\xA9\u00A9\u{2F804}',
    stringEscape2: "\0\b\f\n\r\t\u000b\'\\\xA9\u00A9\u{2F804}",
    stringEscape3: `\0\b\f\n\r\t\u000b\'\\\xA9\u00A9\u{2F804}`,
    arrayEmpty: [], 
    arrayEmptyMultiLine: [ @array
    ],
    arrayEmptyWithAnnotation: [], @array
    arraySimple: [ @array
        "a", @upper
        "b",
    ],
    arrayOnline: ["a", "b"], @array
    arrayExtraComma: ["a", "b",],
    objectEmpty: {},
    objectEmptyMultiLine: { @object
    },
    objectEmptyWithAnnotation: {}, @def("Object4")
    objectSimple: { @ref("Object4")
        k1: "v1", @upper
        k2: "v2",
    },
    objectOneLine: { k1: "v1", k2: "v2" }, @object
    objectExtraComma: { k1: "v1", k2: "v2", },
}

JSON

JSONA is a superset of JSON, borrowing the syntax of ECMAScript to alleviate some of the limitations of JSON.

Support for comments

/**
 multiple lines comment
*/
// single line  comment
{
  @anno /* inline comment */ @anno
}

Use quotes freely on property key

{
  "a": 1,
  b: 2,
  'a': 3,
  `a`: 4,
}

Allow extra trailing commas

{
  a: 3,
  b: 4,
  c: [
    'x',
    'y',
  ],
}

Omit part of floating point numbers

{
  a: 3.,
  b: .1,
  c: 3.1,
}

Multiple bases support

{
  integer: 3,
  hex: 0x1a,
  binary: 0b01,
  octal: 0o12,
}

Support single quotes and backtick quotes

{
  x: 'abc "def" ghi',
  y: "abc 'def' ghi",
  z: `abc "def", 'ghi'`,
}

Multi-line string

{
  x: `abc
  def`
}

Escape string

{
  x: '\0\b\f\n\r\t\u000b\'\\\xA9\u00A9\u{2F804}', // single quote
  y: "\0\b\f\n\r\t\u000b\'\\\xA9\u00A9\u{2F804}", // double quote
  z: `\0\b\f\n\r\t\u000b\'\\\xA9\u00A9\u{2F804}`, // backtick quote
}

Annotation

Annotations are marked with @ followed by a variable name. Annotations may or may not have value.

Insert position

Here's a list of where all the annotations are in JSONA:

{ @anno 
  @anno
  v1: 1, @anno
  v2: {}, @anno
  v3: [], @anno
  v4: [ @anno
  ],
  v5: [
    @anno
  ],
  v6: [
  ], @anno
} @anno
@anno

Annotation value

Annotation value ​​must be enclosed in parentheses, if value is null, parentheses and null can be omitted.

Annotation value must not contain nested annotation.

Command Line

JSONA CLI aims to be an one stop shop tool for working with JSONA files via the command line. The features include validation, formatting, and querying JSONA documents with a jq-like fashion.

Installation

Binary Releases

We pre-compile each release for all major operating systems, these releases can be found on GitHub Releases.

Cargo

If you have a Rust toolchain installed, you can install CLI via the jsona-cli crate from crates.io.

cargo install jsona-cli --locked

Make sure to use --locked if you run into weird compile errors due to incompatible dependencies.

Usage

USAGE:
    jsona [OPTIONS] <SUBCOMMAND>

OPTIONS:
        --colors <COLORS>    [default: auto] [possible values: auto, always, never]
    -h, --help               Print help information
        --log-spans          Enable logging spans
    -V, --version            Print version information
        --verbose            Enable a verbose logging format

SUBCOMMANDS:
    format    Format JSONA documents [aliases: fmt]
    get       Extract a value from the given JSONA document
    help      Print this message or the help of the given subcommand(s)
    lint      Lint JSONA documents [aliases: check, validate]
    lsp       Language server operations

Configuration

Log Level

JSONA CLI uses the Rust tracing library for configurable logging features and respects the RUST_LOG environment variable. All logs regardless of log level are printed to the standard error output.

In most cases you might wish to disable logging below a certain log level. As an example if you wish to only see error messages, you can do the following:

RUST_LOG=error jsona lint foo.jsona

The available log levels:

  • trace
  • debug
  • info
  • warn
  • error

Validation

JSONA CLI supports validation of JSONA files, by default it will only look for syntax errors and some semantic errors such as duplicate keys.

jsona lint foo.jsona

Schema Validation

JSONA supports validation via JSONA Schemas.

jsona lint --schema https://cdn.jsdelivr.net/npm/@jsona/schemastore@0.1.8/openapi.jsona api.jsona
jsona lint -S api.jsona # use default schemastore

Formatting

It is possible to format files in-place or via standard i/o.

jsona fmt foo.jsona

Or

cat foo.jsona | jsona fmt -

By default JSONA CLI will bail on documents that contain syntax errors to avoid destructive edits, you can use the --force flag to suppress this and try to format the invalid document(s) anyway.

Options

Please check formatter options for more details, it is possible to specify overrides via the --option flag:

jsona fmt --option trailing_comma=true foo.jsona

Check

It is possible to check whether the given files are properly formatted via the --check flag. When this flag is supplied, no formatting will be done.

Querying

It is possible to query specific values via a simple query expressions.

jsona get -f foo.jsona 'foo[1].bar'

This will print value in plain json. Use option -A to print json with annotations.

Language Server

The JSONA language server can be used via the CLI and it supports communication via standard i/o or TCP.

Via Standard i/o

jsona lsp stdio

In this mode JSONA CLI expects messages from the standard input, and will print messages intended for the client to the standard output.

Via TCP

jsona lsp tcp --address 0.0.0.0:9181

The server will listen on the given TCP address.

Multiple clients are not supported.

Language Server

JSONA LSP Server and IDE support.

Features

  • Diagnostic
  • Completion
  • Document Symbol
  • Folding Range
  • Formatting
  • Hover
  • Selection Range
  • Associate Schema

Configuration

Formatter Options

This page contains a list of formatting options the formatter accepts.

In some environments (e.g. in Visual Studio Code and JavaScript) the option keys are camelCase to better fit the conventions. For example tailing_comma becomes tailingComma.

optiondescriptiondefault
indent_stringIndentation to use, should be tabs or spaces but technically could be anything2 spaces
trailing_commaPut trailing commas for multiline arrays/objectsfalse
trailing_newlineAdd trailing newline to the sourcefalse
format_keyRemove unnecessary quote or choose better quote for property.false

Jsona Schema

A jsonaschmea is mainly used for:

  • verify jsona document
  • code completions

Developing Schemas

Schemastore is a universal JSON schema store where schemas for popular JSONA schema documents can be found.

See schemastore for more details.

Using schema

JSONA schemas can be assigned to JSONA documents according to the following in priority order starting with the highest priority:

  • set manually in the environment, e.g. as a CLI flag or an IDE setting
  • as an URL under the @jsonaschema in the root of the document
  • configuration file rules
  • contributed by an vscode settings (Visual Studio Code only)
  • an association based on a schemastore

Visual Studio Code Settings

{
  "jsona.schema.associations": {
    "openapi": [
      "api*.jsona",
    ],
  }
}