Markdown Syntax for Object Notation (MSON) is a plain-text syntax for the description and validation of data structures.
- 1 How to Read the Grammar
- 1.1 Markdown Syntax
- 1.2 Notational Conventions
- 1.3 Promises
- 2 Types
- 2.1 Base Types
- 2.1.1 Primitive Types
- 2.1.2 Structure Types
- 2.2 Named Types
- 2.3 Member Types
- 2.3.1 Property Member Types
- 2.3.2 Value Member Types
- 2.1 Base Types
- 3 Type Declaration
- 3.1 Named Declaration
- 3.2 Property Member Declaration
- 3.2.1 Property Name
- 3.2.2 Variable Property Name
- 3.3 Value Member Declaration
- 3.4 Value Definition
- 3.4.1 Value
- 3.4.2 Literal Value
- 3.4.3 Variable Value
- 3.5 Type Definition
- 3.5.1 Type Specification
- 3.5.1.1 Variable Type Specification
- 3.5.2 Type Name
- 3.5.2.1 Variable Type Name
- 3.5.2.2 Wildcard Type Name
- 3.5.3 Type Attribute
- 3.5.1 Type Specification
- 3.6 Description
- 4 Type Sections
- 4.1 Block Description
- 4.2 Member Type Group
- 4.2.1 Member Type Separator
- 4.3 Nested Member Type
- 4.4 Sample
- 4.5 Default
- 4.6 Validations
- 5 Type Inheritance
- 5.1 Mixin Type
- 5.2 One Of Type
- 5.3 Generic Named Type
- 5.4 Member Type Precedence
- 6 Reserved Characters & Keywords
- 6.1 Characters
- 6.2 Keywords
- 6.3 Additional Keywords
- An arrow (→) mark grammar productions that can be read as "is defined by|is defined by a(n)"
- A double arrow (⇒) marks grammar productions that can be read as "contains|contains a(n)"
- Italic text indicates syntactic categories
- A
code span
indicates literal characters, words and punctuations - A pipe character (|) separates alternative grammar productions
- A following [opt] indicates optional syntactic categories and literals
Note this reference is using ATX-style headers (#) and hyphen-style lists (-) exclusively. However you MAY use Setext-style headers and/or asterisk (*) or plus (+) style lists if you prefer.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC2119.
By default, MSON explicitly defines data structures and the meaning of their members without making any assertion to the exclusivity of structures or their members. Further, no assertion is made concerning the presence of defined structures or members. Rather, MSON describes structures that MAY be observed versus what MUST be observed.
However, much like JSON Schema being able to restrict "additionalProperties", MSON allows annotating structures to indicate when they are strictly defined to preclude other structures and members and when they have strict ordering.
In MSON, data structures are described by header-defined and/or list-defined Types and/or combinations thereof built from a limited set of Base Types. A particular Type is defined by its Type Declaration and combination of optional Type Sections.
Type → Type Declaration
Type ⇒ Type Sections [opt]
More specifically:
Type → Type Declaration
Type ⇒ Block Description [opt]
Type ⇒ Member Type Group [opt] | Nested Member Types [opt]
Type ⇒ Sample [opt]
Type ⇒ Validations [opt]
-
Header-defined Named Type
# Person (object) A person. ## Properties - first_name - last_name - address - city - street
-
List-defined Member Type
- person (object) - A person - first_name - last_name - address - city - street
or, equivalently:
- person (Person) - A person
MSON defines a number of distinct base, case-insensitive Primitive and Structure Types from which all data structures are built (sub-typed).
Applies to basic data structure and type definitions. Types that are sub-typed from Primitive Types MUST NOT contain a Member Type Group or Nested Member Types.
-
boolean
Specifies a type with allowed values of
true
orfalse
. -
string
Specifies any string.
-
number
Specifies any number.
Applies to recursive, composite data structure and type definitions. Types that are sub-typed from Structure Types MAY contain a Member Type Group or Nested Member Types.
-
array
Specifies a list of items for values.
-
enum
Specifies an exclusive list of possible Values or Types for values.
-
object
Specifies a structure that contains properties as members.
Users may extend Base Types to define new header-defined Named Types that MAY be referenced to build other Types.
Named Type → Named Declaration | Generic Named Declaration
Named Type ⇒ Type Sections [opt]
# Person (object)
- first_name
- last_name
Markdown lists specify MSON Member Types, which define the structure and types of individual members of Types built from Structure Types. A Member Type that contains Nested Member Types defines an inner, anonymous type that specifies the structure of values of that particular member.
Define individual members of object
type structures.
Property Member Type → Property Member Declaration
Property Member Type ⇒ Type Sections [opt]
Any list of Property Member Types collectively MAY define an implied parent object
type structure.
- person (object) - A person
- first_name
- last_name
- address
- company (string)
Defines a person
Property Member Type with a value that is an explicit object
type structure with members
first_name
, last_name
, and address
and, at the same time, is a member together with company
of another
implied object
structure.
Define individual members of array
or enum
type structures.
Value Member Type → Value Member Declaration
Value Member Type ⇒ Type Sections [opt]
- (array)
- red (string) - A sample value
- green (string)
Defines a particular MSON Type.
Type Declaration → Named Declaration | Generic Named Declaration | Property Member Declaration | Value Member Declaration
Defines a Named Type.
Named Declaration → #
Type Name
Type Definition [opt]
# Person (object)
Defines a Named Type that allows an italicized Variable Type Name to represent a Type Name at any location in the Type Specification of a Variable Type Specification.
Generic Named Declaration → #
Type Name
Variable Type Specification
# One or Many (enum[*T*])
Defines a Property Member Type.
Property Member Declaration → -
Property Name :
[opt] Value Definition [opt] -
[opt] Description [opt]
- person (object) - A person
The optional :
is only applicable in the case where a Value Definition is present and includes a Value.
- company: Apiary (string)
Defines the name of a property in an object
type structure.
Property Name → Literal Value | Variable Property Name
- customer (object)
Defines a Property Member Declaration with a Property Name "customer".
Defines a Property Name that is associated with a specific Value Definition in an object
type structure
that MAY be any arbitrary name in an actual implementation. The Value of the Variable Property Name serves as
a sample.
Variable Property Name → *
Value Definition*
In the case of specifying a Variable Property Name, the Value Definition MAY reference a Named Type
that MUST be sub-typed from a string
Primitive Type.
*rel (Custom String)* (object)
Where rel
is a sample value for the arbitrary Property Name of a Property Member Declaration.
Defines a Value Member Type. A Value Member Declaration MUST only be used to define structures of array
or enum
Member Types.
Value Member Declaration → -
Value Definition -
[opt] Description [opt]
The optional -
is only applicable in the case where a Description is provided.
- (array)
Every Member Type MAY specify type information associated with values in a structure or member in a structure. This includes a Value Definition that may include literal or sample Values and a Type Definition, including a Type Specification and/or Type Attributes, of associated types.
Value Definition → Value [opt] Type Definition [opt]
A Value Definition MUST include at least a Value or a Type Definition. A Value Definition of an
object
Member Type MUST NOT specify a Value.
5, 6 (array)
Defines a Value Definition for an array
type structure with sample values "5" and "6".
Defines either sample or actual value(s) in Member Types based on the associated Type Definition in a Value Definition.
Value → Literal Value | Variable Value | Values List
Values List → Value | Value,
Values List
A Values List MUST only be used with array
or enum
Structure Types or Named Types derived from them.
By default:
- A Value Definition that incorporates a Values List but has no Type Definition implies an
array
type structure.
- list: 1, 2, 3
is equivalent to:
- list: 1, 2, 3 (array)
Where "1", "2", and "3" are sample values of the array
structure.
- A Value Definition that incorporates a Values List defines fully-qualified values of an
enum
type structure.
- colors: red, green (enum)
Where "red" and "green" are fully-qualified values of the colors
enumeration.
Literal value of a type instance. Some limitations apply (see Reserved Characters & Keywords).
5
Defines a Value that is not concrete using Markdown italics.
Variable Value → *
Literal Value*
A Variable Value MAY be used to indicate a Variable Property Name in a Property Member Declaration or more generally, a sample value in a Value Definition.
*rel*
Explicitly specifies the type of a value in an MSON instance.
Type Definition → (
Type Specification [opt] ,
[opt] Type Attributes List [opt])
Type Attributes List → Type Attribute | Type Attribute,
Type Attributes List
A Type Definition MUST separate multiple items with commas and is order-independent.
(enum, optional)
Defines sub-typed Base Types or Types for a particular Type.
Type Specification → Type Name | Type Name[
Nested Type Name List]
Nested Type Name List → Type Name | Type Name,
Nested Type Name List
An array
or enum
Value Definition MAY specify the Type Specifications of implied
Nested Member Types members in-line using []
as a Nested Type Name List.
array[number, string]
Indicates a array
type structure MAY include distinct numbers or strings as values.
Defines a variable Type Specification to indicate generic Named Types.
Variable Type Specification → Type Specification
A Variable Type Specification MUST include at least one Variable Type Name.
# One or Many (enum[*T*])
References the name of a type in Base Types or Named Types. Some limitations apply (see Reserved Characters & Keywords).
Type Name → Literal Value | Variable Type Name | Wildcard Type Name | Referenced Type Name
Referenced Type Name → A valid Markdown-style link, where the link name MUST be a Literal Value
A Variable Type Name MUST only be used in two situations:
- As a Type Name in a Type Definition for a Generic Named Type.
- As an associated Type Name in Nested Member Types of the Generic Named Type.
A Referenced Type Name MAY be used to link to a Type Name defined in another location in an MSON document solely as a navigation convenience.
An italicized variable that MAY be used in place of a Type Name for a Type Definition in a Generic Named Declaration.
Variable Type Name → *
Literal Value*
Indicates any type MAY be possible.
Wildcard Type Name → *
A Wildcard Type Name MAY only be used in a Type Specification for Member Types.
Defines extra attributes associated with the implementation of a type.
required
- instance of this type is requiredoptional
- instance of this type is optional (default)fixed
- instance of this type structure and values are fixednullable
- instance of this type Value MAY be unset (e.g.null
ornil
)sample
- Alternate way to indicate a Value is a sample. See Sample.default
- Alternate way to indicate a Value is a default. See Default.
A sample
Type Attribute is mutually exclusive with default
.
Describes a Member Type in-line.
Description → -
Markdown-formatted text
- name: Andrew (string) - A Description
Types MAY contain any Block Description, Member Type Group, Nested Member Types, Sample, Default and/or Validations Type Sections. Apart from a Block Description, multiple Type Sections MAY be specified and MAY have any order.
# Person (object)
An additional
multi-line description
- here
- there
## Sample
...
## Properties
- first_name
- last_name
## Validations
...
## Sample
Another ...
In general, Type Sections nested under:
- A Named Declaration MUST use header-defined (
##
) variations. - A Property Member Declaration or Value Member Declaration MUST use list-defined (
-
) variations.
Describes a Type using a nested (multi-line) Markdown text block.
Block Description → Markdown-formatted text
A Block Description MUST be located directly under a Type Declaration and MUST start with text. Markdown lists MAY be included in a Block Description after initial text content and are considered part of the block text.
- name: Andrew (string) - A Description
An additional
multi-line description.
- here
- there
More text.
Note that here
and there
are NOT Nested Member Types but rather are part of a Markdown list in the
Block Description.
A Member Types Block Description MUST escape Member Type Separator Keywords as a code span
when used in a Markdown list.
- person (object)
This person does not have:
- `Properties`
- first_name
- last_name
- Properties
- given_name
- surname
A Member Type Group delineates Nested Member Types and MUST be used when other Type Sections are present.
Member Type Group → -
Member Type Separator | ##
Member Type Separator
Member Type Group ⇒ Nested Member Types
In order to specify Nested Member Types after a Block Description, Types MUST use an appropriate Member Type Group to indicate the end of the Block Description and the beginning of a Nested Member Types list.
-
Named Type
A header-defined (
##
) Member Type Group SHOULD be nested one additional header level under the associated Named Type, when required.# Person (object) An additional multi-line description - here - there ## Properties - first_name - last_name
-
Member Type
A list-defined (
-
) Member Type Group SHOULD be nested one indentation level under the associated Member Type.- person (object) An additional multi-line description - here - there - Properties - first_name - last_name
A Member Type Group of an appropriate type MUST be used to define Nested Member Types whenever any other Type Section is specified at the same level.
-
Without a Block Description
- Nested Member Types SHOULD be nested directly under a Type Declaration whenever possible.
- Nested Member Types MAY be used without a Member Type Group in a Named Type, even if other Type Sections are present, if they are nested directly under the Type Declaration.
# Person (object) - first_name - last_name ## Sample ...
-
With a Block Description
A Member Type Group MUST be used to define Nested Member Types.
# Person (object) Just an ordinary person ## Properties - first_name - last_name
Defines the names of separators to indicate the beginning of a section of Nested Member Types.
Member Type Separator → Items
| Members
| Properties
-
Array Structures - MUST use
Items
for a Member Type Separator -
Enum Structures - MUST use
Members
for a Member Type Separator -
Object Structures - MUST use
Properties
for a Member Type Separator
Types built from Structure Types MAY contain Nested Member Types, which are defined using nested Markdown lists of allowed Member Types.
A Member Type that contains Nested Member Types defines an inner, anonymous type that specifies the structure of values of that particular member.
Nested Member Types → Member Types
By Default:
-
Un-nested Member Types
A Member Type that does not contain Nested Member Types and does not contain a Type Definition implies a
string
Type Specification.- count: 1
Implies:
- count: 1 (string)
-
Object Structures
A Property Member Type without a Type Definition that contains Nested Member Types implies an
object
type structure.- address - city - state
Implies:
- address (object) - city - state
-
Array Structures
A Member Type with an
array
Type Definition that contains Nested Member Types specifies anarray
type structure that MAY contain items of the specified type and sample values per the particular Value Definition.- colors (array) - red (string) - 5 (number)
Implies an
array
structure whose individual items MAY be strings or numbers with sample values "red" and "5", respectively. -
Enum Structures
A Member Type with an
enum
Type Definition that contains Nested Member Types specifies anenum
type structure that MUST only contain items of the specified type and values per the particular Value Definition.- colors (enum) - red (string) - 5 (number)
Implies a
colors
Property Member Type that MUST only have a value of the string "red" or the number 5.A Variable Value in a Nested Member Type under a
enum
type structure indicates an allowed type with an associated sample value.- colors (enum) - red (string) - *5* (number)
Implies a
colors
Property Member Type that MUST have either the string "red" or any number as a value, where "5" is a sample of anumber
value. -
Named Types
Nested Member Types MAY be nested directly under a Named Declaration when there are no other Type Sections present.
# Person (object) - first_name - last_name
With a fixed
Type Attribute:
-
If a Named Type or Member Type annotates its type as
fixed
, all Nested Member Types inherit thefixed
attribute as well.- person (object, fixed) - name
Implies:
- person (object, fixed) - name (fixed)
-
An
array
based Named Type or Member Type MAY specifyfixed
to indicate the structure is a "fixed ordered list" of only the specified values and/or types, if any, of its Nested Member Types.- colors (array, fixed) - red - green
Implies a fixed-list
array
structure that MUST only contain the two items "red" and "green" in that order.- components (array, fixed) - (object) - (string)
Implies a fixed-list
array
structure that MUST only contain the two items of an arbitraryobject
andstring
in that order. -
An
object
based Named Type or Member Type MAY specifyfixed
to indicate a "value object" where all the properties MUST be present and the values of the properties MUST be the values specified, if any, in its Nested Member Types. Further, such anobject
type structure MUST NOT contain any other properties.- person (object, fixed) - first_name: Andrew - last_name: Smith
Implies a "value object" that MUST contain only the properties "first_name" and "last_name" with the values "Andrew" and "Smith", respectively.
- person (object, fixed) - first_name - last_name
Implies an
object
that MUST contain only the properties "first_name" and "last_name", respectively. -
Individual Nested Member Types MAY override inherited behavior from a
fixed
inherited type by using anoptional
attribute and/or MAY indicate values are samples using a Variable Value.- person (object, fixed) - first_name - last_name (optional)
Implies a "value object" that MUST contain the property "first_name" and MAY contain the property "last_name".
- colors (array, fixed) - red - *green*
Implies an
array
type structure that MUST contain "red" as an item and MAY contain any other strings, where "green" is a sample value.
Defines alternate sample Values for Member Types as a nested Markdown list with (multi-line) text.
Sample → - Sample
| - Sample :
Value | ## Sample
Sample ⇒ Markdown-formatted text | Value Member Types
A Type MAY have multiple Sample lists.
-
Named Types
A header-defined (
##
) Sample MUST be nested one additional header level under the associated Named Type if a Block Description is used.# Colors (array) A list of colors ## Sample - red ## Items - (string) ## Sample - blue - green
A
sample
Type Attribute MUST NOT be used in the Type Definition of a Named Declaration. -
Member Types
A list-defined (
-
) Sample SHOULD be nested one indentation level under the associated Member Type.- colors (array) - Sample: red - Sample - blue - green
A
sample
Type Attribute MAY be used to indicate a Value in a Value Member Type is a sample value.- list: 3, 4 (enum, sample)
Is equivalent to:
- list: *3, 4* (enum)
Which, is equivalent to:
- list (enum) - Sample - 3 - 4
A
default
Type Attribute MUST NOT be used in the Type Definition of a Property Member Declaration.
Indicates Values for Member Types as a nested Markdown list with (multi-line) text are defaults.
Default → - Default
| - Default :
Value | ## Default
Default ⇒ Markdown-formatted text | Value Member Types
A Type MAY have one Default Type Section. A Default for a Member Type MAY also indicate a Sample.
-
Named Types
A header-defined (
##
) Default MUST be nested one additional header level under the associated Named Type if a Block Description is used.# Colors (array) A list of colors ## Default - red ## Items - (string)
A
default
Type Attribute MUST NOT be used in the Type Definition of a Named Declaration. -
Member Types
A list-defined (
-
) default SHOULD be nested one indentation level under the associated Member Type.- colors (array) - Default: red
A
default
Type Attribute MAY be used to indicate a Value in a Value Member Type is a default value.- list: 4 (enum, default) - 3 - 4
is equivalent to:
- list: 3, 4 (enum) - Default: 4
A
default
Type Attribute MUST NOT be used in the Type Definition of a Property Member Declaration.
Reserved for future use.
A Member Type or Named Type that inherits from another Named Type also inherits any Nested Member Types in the same order they are defined in the inherited Named Type and in order based on the placement of the Mixin Type.
# Person (object)
- first_name
- last_name
And:
- person (Person)
- address
Implies the same structure as:
- person (object)
- first_name
- last_name
- address
Where the inherited Member Types from Person
Named Type are listed first.
MSON defines a Mixin Type that supports multiple inheritance from another Named Type. The Named Type being inherited MUST be a Structure Type or its sub-type.
Nested Member Types defined in and inherited from the mixed-in Named Type are added at the same indentation level of the Mixin Type.
Mixin Type → - Include
Type Name | - Include
Type Definition
Example 1
# Person (object)
- first_name
- last_name
And:
- formal_person (object)
- prefix: Mr
- Include Person
Implies the same structure as:
- formal_person (object)
- prefix: Mr
- first_name
- last_name
Example 2
Alternately:
- formal_person (object)
- Include Person
- prefix: Mr.
Implies the same structure as:
- formal_person (object)
- first_name
- last_name
- prefix: Mr.
A Mixin Type MUST use an appropriate Member Type Separator in a Member Type Group in order to specify Nested Member Types after a Block Description.
- address (object)
An address
- Properties
- Include Address
MSON defines a One Of Type that can be used to describe mutually exclusive sets of Nested Member Types. A
One of Type MUST only be used to define Property Member Types for a object
type structure.
One of Type → - One Of
One of Type ⇒ Member Type Group
One of Type ⇒ Nested Member Types
One of Type ⇒ Mixin Type
One of Type ⇒ One of Type
- first_name
- One Of
- last_name
- One of
- given_name: Smith
- suffixed_name: Smith, Sr.
Implies values with a structure of:
- first_name
- last_name
Or:
- first_name
- given_name: Smith
Or:
- first_name
- suffixed_name: Smith, Sr.
A One Of Type MUST use a Properties
Member Type Separator in a Member Type Group:
-
In order to specify Nested Member Types after a Block Description.
- address (object) An address - Properties - One Of - state - province
-
When it contains a Member Type Group.
- person (object) - One Of - full_name - Properties - first_name - last_name
Defines a Named Type that allows an italicized Variable Type Name to represent a Type Name at any location in a Type Specification.
Generic Named Type → Named Type
By default:
-
A Named Type that contains at least one Variable Type Name is a Generic Named Type.
-
A Variable Type Name in a Type Specification MAY only be used in the Type Definition of explicitly defined Nested Member Types in the Generic Named Type and MUST NOT define any implied Nested Member Types.
-
Inherited type as a variable
# Address Decorator (*T*) - address # Person (object) - first_name - last_name
And:
- decorated_person (Address Decorator(Person))
Implies the same structure as:
- decorated_person (object) - first_name - last_name - address
-
Type passed into explicitly defined Member Types
# One or Many (*S*[*T*, string]) - (*T*) - (array[*T*])
And:
- rel (One or Many(enum, object))
Implies the same structure as:
- rel (enum) - (string) - (object) - array[object]
Implementers of tooling for MSON structures SHOULD use an inheritance precedence such that the last redundant Member Type specified in a list at the same indentation level appends or overrides a previously defined Member Type.
# Person (object, fixed)
- first_name
- last_name
- address (object)
-
Add/Override Attributes
Example 1
- person (Person) - last_name (optional)
Is literally the same as:
- person (object) - first_name (fixed) - last_name (fixed) - address (object, fixed) - last_name (optional)
Which implies a structure the same as:
- person (object) - first_name (fixed) - last_name (optional) - address (object, fixed)
Example 2
- person (object) - first_name (optional) - Include Person
Is literally the same as:
- person (object) - first_name (optional) - first_name (fixed) - last_name (fixed) - address (object, fixed)
Which implies a structure the same as:
- person (object) - first_name (fixed) - last_name (fixed) - address (object, fixed)
Example 3
- person (object) - Include Person - first_name (optional)
Is literally the same as:
- person (object) - first_name (fixed) - last_name (fixed) - address (object, fixed) - first_name (optional)
Implies a structure the same as:
- person (object) - first_name (optional) - last_name (fixed) - address (object, fixed)
-
Add New Member Types
- person (Person) - citizenship
Implies a structure the same as:
- person (object, fixed) - first_name - last_name - address (object) - citizenship
-
Override Member Types
- person (object) - Include Person - address (string)
Is literally the same as:
- person (object) - first_name (fixed) - last_name (fixed) - address (object, fixed) - address (string)
Implies a structure the same as:
- person (object) - first_name (fixed) - last_name (fixed) - address (string)
When using following characters or keywords in a Property Name, Literal Value or Type Name the name
or literal MUST be escaped in backticks `
. Otherwise, a code span
MAY be used for any arbitrary formatting
and has no specific meaning in an MSON document.
:
, (
,)
, <
, >
, {
, }
, [
, ]
, _
, *
, -
, +
, `
Property
, Properties
, Item
, Items
, Member
, Members
, Include
, One of
, Sample
Note keywords are case-insensitive.
Following keywords are reserved for future use:
Trait
, Traits
, Parameter
, Parameters
, Attribute
, Attributes
, Filter
, Validation
, Choice
, Choices
,
Enumeration
, Enum
, Object
, Array
, Element
, Elements
, Description