GithubHelp home page GithubHelp logo

mson's Introduction

Markdown Syntax for Object Notation

This document provides an introduction to Markdown Syntax for Object Notation (MSON), a Markdown syntax compatible with describing JSON and JSON Schema.

What?

MSON is a plain-text, human and machine readable, description format for describing data structures in common markup formats such as JSON, XML or YAML.

What for?

The aim of this description format is to facilitate the discussion (and thus validation) of data structures. The format, being agnostic to the common markup formats, is well suited for "resource & representations" and "content negotiation" scenarios.

In addition, this format also offers (limited) serialization functionality.

Similar to the original Markdown to HTML (markup) conversion, MSON enables conversion to other markup formats.

Who & Why?

This format is being developed by Apiary as a part of the API Blueprint syntax to provide a means for description and validation of HTTP payloads and DRY, media-type agnostic, resource descriptions and to simplify content-negotiation.

NOTE: While this document focuses primarily on JSON and JSON Schema examples, the underlying specification will ultimately allow producing XML or YAML representations from MSON.

Notational Conventions

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.

Example 1

A simple object structure and its associated JSON expression.

MSON

- id: 1
- name: A green door
- price: 12.50
- tags: home, green

Rendered Markdown

  • id: 1
  • name: A green door
  • price: 12.50
  • tags: home, green

JSON

{
    "id": "1",
    "name": "A green door",
    "price": "12.50",
    "tags": [ "home", "green" ]
}

NOTE: By default, a Markdown list item is considered to be a string type.


Example 2

A Named Type with its associated JSON expression and JSON Schema.

MSON

# Product
A product from Acme's catalog

## Properties

- id: 1 (number, required) - The unique identifier for a product
- name: A green door (string, required) - Name of the product
- price: 12.50 (number, required)
- tags: home, green (array[string])

Rendered Markdown

Product

A product from Acme's catalog

Properties
  • id: 1 (number, required) - The unique identifier for a product
  • name: A green door (string, required) - Name of the product
  • price: 12.50 (number, required)
  • tags: home, green (array[string], fixed-type)

JSON

{
    "id": 1,
    "name": "A green door",
    "price": 12.50,
    "tags": [ "home", "green" ]
}

NOTE: The id and price sample values are numbers given the explicit declaration of their base type of number vs. the default of string as in Example 1.

JSON Schema

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "Product",
    "description": "A product from Acme's catalog",
    "type": "object",
    "properties": {
        "id": {
            "description": "The unique identifier for a product",
            "type": "number"
        },
        "name": {
            "description": "Name of the product",
            "type": "string"
        },
        "price": {
            "type": "number"
        },
        "tags": {
            "type": "array",
            "items": {
                "type": "string"
            }
        }
    },
    "required": ["id", "name", "price"]
}

NOTE: This proposal covers only basic features of JSON Schema. At this moment, it is out of the scope of this syntax to support all the JSON Schema keywords (such as uniqueItems, exclusiveMinimum, etc.).


MSON Language Specification

The rest of this document covers some advanced syntax examples. Refer to the MSON Language Specification for the complete MSON Grammar Reference.

Quick Links

Objects & Arrays

By default, a Markdown list item with a nested Markdown list is considered to be an object structure:

MSON

- address
    - street
    - city
    - state

JSON

{
    "address" : {
        "street": "",
        "city": "",
        "state": ""
    }
}

If a Markdown list's items are intended to be literals (represent array values), the type of the parent list item MUST be explicitly set to array:

MSON

- address (array)
    - street
    - city
    - state

Or, alternately:

- address: street, city, state (array)

In this latter case, using a comma-separated list of values, the type (array) is implied and thus MAY be omitted.

JSON

{
    "address": [ "street", "city", "state" ]
}

NOTE: The values "street", "city", and "state" are solely sample values of the address array in this example. No constraints are implied on the quantity or types of values in such an array other than that they MAY be string literals.

Advanced Objects

Non-uniform Property

A Property whose value can be of different types is defined by the enum structure type:

MSON

- tag (enum)
    - green (string)
    - (object)
        - tag_id: 1
        - label: green

Rendered Markdown

  • tag (enum)
    • green (string)
    • (object)
      • tag_id: 1
      • label: green

JSON

{
    "tag": "green"
}

or

{
    "tag": {
        "tag_id": "1",
        "label": "green"
    }
}

NOTE: In an enum structure, in contrast to an array type structure, a value like "green" is a fully-qualified value of the enumeration vs. being a sample value.


Mutually Exclusive Properties

By default, all properties are optional and may or may not be included in the object. If there is a choice of mutually exclusive properties available MSON defines a One Of type:

MSON

- city
- One Of
    - state
    - province
- country

Rendered Markdown

  • city
  • One Of
    • province
    • state
  • country

JSON

{
    "street": "",
    "province": "",
    "country": ""
}

or

{
    "street": "",
    "state": "",
    "country": ""
}

NOTE: Because an enum type MUST define a list of types vs. properties and by default an un-nested Markdown list defines properties of an implied object structure, the One Of type declaration MUST only be used to indicate mutually exclusive properties in an object structure.


Advanced Arrays

Array of Mixed Types

MSON

- tags (array)
    - hello (string)
    - 42 (number)

Rendered Markdown

  • tags (array)
    • hello (string)
    • 42 (number)

JSON

{
    "tags": [ "hello", 42 ]
}

MSON

- (array)
    - (object)
        - name: snow (string)
        - description (string)
    - 42 (number)

Rendered Markdown

  • (array)
    • (object)
      • name: snow (string)
      • description (string)
    • 42 (number)

JSON

[
    {
        "name": "snow",
        "description": ""
    },
    42
]

Array of Arrays

MSON

- (array)
    - 1, 2, 3, 4 (array[number])

Rendered Markdown

  • (array)
    • 1, 2, 3, 4 (array[number])

JSON

[
    [ 1, 2, 3, 4 ]
]

Multi-line Descriptions

In the case where a one-liner description is not sufficient, a multi-paragraph text block is the way to go.

MSON

- id: 1 (number, required) - The unique identifier for a product
- name: A green door (string, required)

    Lorem ipsum dolor sit amet, consectetur adipiscing elit.

    Sed sed lacus a arcu vehicula ultricies sed vel nibh. Mauris id cursus felis.

    Interdum et malesuada fames ac ante ipsum primis in faucibus.

    - unus
    - duo
    - tres
    - quattuor

- price: 12.50 (number, required)
- tags: home, green (array)

For a multi-line description of a structure type, an Items, Members , or Properties keyword MUST be used to avoid conflict with potential list item values that are part of the description:

- tags (array)

    Lorem ipsum dolor sit amet, consectetur adipiscing elit.

    Sed sed lacus a arcu vehicula ultricies sed vel nibh. Mauris id cursus felis.

    Interdum et malesuada fames ac ante ipsum primis in faucibus.

    - unus
    - duo
    - tres
    - quattuor

    - Items
        - home
        - green

NOTE: Unus ... quattuor are considered part of the text block vs. defining items of the array.

Escaping

Markdown code span element syntax (` `) is used to escape reserved Keywords that should just be interpretted as literals as well as other constructs that may be erroneously interpreted by an MSON parser as meaningful.

For non-Keywords, a code span can be used for formatting Markdown as an aesthetic preference.

MSON

- listing (object)

    Our real estate listing has different properties available.

    - `Properties`
        - This one.
        - That one.

    - Properties
        - description (string)
        - date_listed (string)
        - `some:location`: local (string)

Rendered Markdown

  • listing (object)

    Our real estate listing has different properties available.

    • Properties

      • This one.
      • That one.
    • Properties

      • description
      • date_listed
      • some:location: local (string)

NOTE: In this example, the first "Properties" string is part of the multi-line block description whereas the second defines the properties of the listing object.


Variable Property Name

Variable property name (key) is defined using italics. Note that a variable property cannot be required.

MSON

- _links
    - *self*
        - href: a URI

Rendered Markdown

  • _links
    • self
      • href: a URI

JSON

{
    "_links": {
        "self": {
            "href": "..."
        },
        "users": {
            "href": "..."
        }
    }
}

Type Definition

Additional Named Types can be defined using a Markdown header:

MSON

# Address (object)
Description is here! Properties to follow.

## Properties
- street
- state
- zip

The same entity defined as an address property:

- address (object)

    Description is here! Properties to follow.

    - Properties
        - street
        - state
        - zip

The same address property referencing the previously Named type:

- address (Address)

Referencing

Anywhere a type is expected, a top-level MSON Named Type can be referenced.

MSON

# Address (object)
- street
- city
- state
- zip

# User (object)
- first_name
- last_name
- address (Address)

Rendered Markdown

Address (object)
  • street
  • city
  • state
  • zip
User (object)
  • first_name
  • last_name
  • address (Address)

JSON

{
    "first_name": "",
    "last_name": "",
    "address": {
        "street": "",
        "city": "",
        "state": "",
        "zip": ""
    }
}

Mixins

To include (mixin) values or properties in another Named Type use the Include keyword followed by a reference to the
MSON Named Type.

MSON

# Address Object
- street
- city
- state
- zip

# User Object
- first_name
- last_name
- Include Address

Rendered Markdown

Address Object
  • street
  • city
  • state
  • zip
User Object
  • first_name
  • last_name
  • Include Address

JSON

{
    "first_name": "",
    "last_name": "",
    "street": "",
    "city": "",
    "state": "",
    "zip": ""
}

NOTE: A mixin can only use a Named Type that is derived from the same type of structure including the mixin. Further, the parent structure inherits all the members of the included Named Type and maintains the order the members were originally defined.

mson's People

Contributors

danielgtaylor avatar fosrias avatar goganchic avatar honzajavorek avatar kiriakos avatar kylef avatar paraskakis avatar pksunkara avatar sharpseeer avatar smizell avatar stkent avatar w-vi avatar zdne avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mson's Issues

Allow example values for non-member types

This may be related to aliases, which I've seen has already been decided against.

There are times it is useful to define a Named Type of a primitive in order to imply a specific format. Currently, the only way to define a Named Type of a primitive is:

# Email (string)

Doing so does not allow an example value to be provided for the type, which means anything that references them must provide the example value:

+ Attributes (array[Email])

will render as an empty array. Currently, the only way to achieve the desired effect seems to be always specifying an example value

+ Attributes (array)
    - [email protected] (Email)

Document how to give samples for named primitive types

After trying a couple of different alternatives trying to set a sample value for a named primitive type using a ## Sample heading, this is what I came up with.

## Data Structures

### DummyNamedStringType (string)
This dummy string doesn't receive a proper sample value unless it's on the same line as the sample header.

#### Sample: [email protected]

Some questions arise.

As I couldn't find this syntax in the documentation, I think it would be nice to add it. Thanks!

Longer example

See also http://docs.namedprimitivetypesamplevalue.apiary.io/ for the rendered output.

FORMAT: 1A
HOST: http://polls.apiblueprint.org/

# NamedPrimitiveTypeSampleValue

This example shows how to set default sample values for named primitive types.

## Dummy Endpoint [/dummy]

### Get a Dummy [GET]

+ Response 200 (application/json)

    + Attributes (Dummy)

## Data Structures

### DummyNamedStringType (string)
This dummy string doesn't receive a proper sample value unless it's on the same line as the sample header.

#### Sample: [email protected]

### DummyNamedNumberType (number)
This dummy number doesn't receive a proper sample value unless it's on the same line as the sample header.

#### Sample: 1337

### DummyNamedBooleanType (boolean)
This dummy boolean doesn't receive a proper sample value unless it's on the same line as the sample header.

#### Sample: true

### Dummy
- dummyString (DummyNamedStringType)
- dummyNumber (DummyNamedNumberType)
- dummyBolean (DummyNamedBooleanType)

Basic data type aliases

I'd argue it would greatly improve FTUE if aliases would be added, namely:

  • int and integer for number
  • list for array

Expressing arrays of a fixed (non-inherited) type

In MSON, it's not possible to express arrays which MUST contain a certain type of element. But the contents of the array does not have fixed values.

For example, I might want to describe a data structure which is an array of User objects. Where the array SHOULD only contain User objects, and other types of items inside the array are not valid.

In JSON Schema, I can represent this as follows:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "members": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string"
          }
        }
      }
    }
  }
}

Where I have a JSON Structure as follows, which validates using the previous schema:

{
  "name": "Blueprint Team",
  "members": [
     { "username": "kyle" }
   ]
}

However, a user without a username wouldn't validate:

{
  "name": "Blueprint Team",
  "members": [
     { "name": "Kyle" }
   ]
}

It should be possible to express what I have outlined above in API Blueprint / MSON. For example, I may intend to describe an array of User with the following blueprint:

## Team List [/teams]
### Create Team [POST]

+ Request (application/json)
    + Attributes
        + name: Blueprint Team
        + members (array[User])

+ Response 202

## Data Structures
### User

+ username: kyle

However, given the MSON specification array[User] does not mean an array of only User. But instead, an array which MAY contain User which ultimately means generated JSON Schema's cannot say that the array MUST contain ONLY User.

conditionally requiring properties

Hello, is there a way to indicate that a parameter is required if and only if another parameter is passed?

For example, I have an endpoint that returns a list of appointments. That list can be filtered using startDate and endDate. They are both required if and only if one of them is passed, otherwise, they're optional.

I see something similar using the One Of syntax.

Best,
James

Escaping of underscores does not work in all cases

I have hit the issue in Apiary/Blueprint where I cannot use underscores in attribute names since they are first interpreted as markdown special characters.

I understand that backticks can be used to escape the attribute names but this does not always work.

Example;

http://docs.parameterfail.apiary.io/

The use of backticks in the description of the account_id parameter do not escape it in this case and it means that it is impossible to reference the attribute itself, or other related attributes when you are providing descriptive text for them.

Generate JSON Schema custom keys

Hi there,

I was wondering if it was possible to add arbitrary keys in the generated JSON Schema. For instance:

# Test

- text (string) - My string

Currently generates:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "text": {
      "type": "string",
      "description": "My string"
    }
  }
}

But how could I generate for instance?

{
  "id": "https://example.org/test",
  "description": "My test schema",
  "$myothercustomkey": true,
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "text": {
      "type": "string",
      "description": "My string"
    }
  }
}

Limiting string lengths

Hey, is there a way to constrain strings to a certain length, translating to json schema maxLength? Something like string[255] would be nice.

Is there a way how to reuse enum Members declaration?

I'd like to be as DRY as possible and do not replicate enum Members
Is something like this possible to do in MSON:

## TypeEnum (enum[string])
+ Members
  + `type_1`
  + `type_2`
  + `type_3`

## SomeObject (object)
+ `type_name` (TypeEnum, required)

## SomeOtherObject (object)
+ `other_type_name` (TypeEnum, required)

Thanks!

there is any MSON implementation in Ruby ?

Hi all
that in't a real issue, but just a question: there is any MSON implementation in Ruby language ?
I mean a MSON (Markdown) to JSON (and so in hash internal data structures) and viceversa ?

thanks
giorgio

Clarify meaning of number

For number primitive type, specification says:

Specifies any number.

I think it should be specified what any means. Integers only? Signed? Unsigned? Decimal points—fixed or floats?

If "any" truly means "all of the above", I think it would be useful to explicitly mention it in spec.

`null` in enum list

I have MSON:

- options (enum, nullable, required)
    - (object)
        - type: `example` (string, required)
    - (object)
        - preview: `http://preview.com` (string, required)
        - detail: `http://preview.com` (string, required)

And if field options returns null i receive error message from dredd:

At '/options' - Data does not match any schemas from "anyOf"

I tested other options:

- options (enum, required)
    - (object, nullable)
        - type: `example` (string, required)
    - (object, nullable)
        - preview: `http://preview.com` (string, required)
        - detail: `http://preview.com` (string, required)
- options (enum, required)
    - (object)
        - type: `example` (string, required)
    - (object)
        - preview: `http://preview.com` (string, required)
        - detail: `http://preview.com` (string, required)
    - (nullable)
- options (enum, required)
    - (object)
        - type: `example` (string, required)
    - (object)
        - preview: `http://preview.com` (string, required)
        - detail: `http://preview.com` (string, required)
    - (string, nullable)

It's all doesn't work for me.

Use markdown links in mson

If I was to have the following document

- name: A door
- destination: [kitchen](http://domain.io/rooms/kitchen)
- colour: green
- description: A green door

It would be great if it could be rendered in hal like the following

{
    "_links": {
        "self": { "href": "/whatever" },
        "destination": { "href": "http://domain.io/rooms/kitchen", "title": "kitchen" }
    },
    "name": "A door",
    "colour": "green",
    "description": "A green door"
}

That way, formats that can express outbound links in a defined manner (like HAL can) are able to do so without embedding the Hal '_links' field into the markdown representation.

You could format this completely differently for json-api or Siren too, depending on what's required.

Thoughts? :)

Ability to set `additionalproperties: false`

Hi, I recently know apiblueprint and dredd. And I really like these concepts so that we create https://github.com/wantedly/apiblueprint-rails gem to automatically create apiblueprint voilerplate when rails scaffolding using rails generate apiblueprint command.

Here, I want to discuss how to write additionalproperties: false properties in MSON, since additionalproperties option is really important feature to run the test in dredd.

Background

I've been using JSON Schema in my company to maintain documents and specs, but that is really hard to maintain. That's mainly because the difficulty to write json. Even I just added one column to the model, I need to change json schema in many place.

So, the workflow
write attributes list as mark down => convert to json schema => test in dredd
is great idea to maintain consistency between codes and documents.

However, the dredd test passes even if I add an attribute to the model and the api response contains an additional field. After I investigated the reason, I found that I need to add additionalproperties: false to json schema. However, current MSON cannot write this option.
The advanced example of API Blueprint shows the way to write, but this need to write json schema directly so that all the merits of MSON suddenly disappeared in such way.

Suggestion

I have 2 ideas to enable to write additionalproperties option.

To begin with, please note that additionalProperties is validation for objects.

    5.4.  Validation keywords for objects
        5.4.1.  maxProperties
        5.4.2.  minProperties
        5.4.3.  required
        5.4.4.  additionalProperties, properties and patternProperties
        5.4.5.  dependencies

http://json-schema.org/latest/json-schema-validation.html

So the way to add as object properties like required is sensible.

Idea1: user (object, required, additionalproperties:false, minproperties:1)

Enable to write values for each attributes options.

This can cover, minproperties and maxproperties option. (dependency is the other story though)

Idea2: user (object, required, nullable, noadditionalproperties)

Enable to write 2 commands:

  • addtionalproperties: it becomes additionalproperties: true in json schema
  • noadditionalproperties: it becomes additionalproperties: false in json schema

noprefix to set target option false is common especially in shell command, so this maybe easy to understand for almost all engineers. Additionally this may not require additional parsing logic.
Since addtionalproperties: true is default, just adding noadditionalproperties option is also acceptable for me.

I personally think Idea2 is simple so I prefer this, though idea1 has wide coverage of validations.

How do you think?
If the policy is decided, I (and my coworker) am willing to send pull request. Please take a look and give me response.

Ability to select a particular sample of a referenced name type

I recently found myself in the following situation: I defined a couple of Named Type objects, one referencing the other(e.g., object A has a reference to object B). Each of the objects may have a couple of Sample sections. I'd like to have the ability, when defining the Sample section of object A, to reference a particular Sample in object B's definition. This would allow me to document difference scenarios of the API.

Moreover, I'd like to see Samples that are just instantiations of the type definitions, or that are somehow validated against the type definition (in order to avoid inconsistencies between samples and the type definition)

MSON generator by JSON (no issue)

I make simple MSON generator
https://msongenerator.herokuapp.com/

For example
JSON:

{
  "rider_items": [
    {
      "id": 867,
      "artist_program_id": 1742,
      "created_at": "2016-09-23T11:30:03.863+03:00",
      "updated_at": "2016-09-23T11:30:03.863+03:00",
      "rider_item_variants": [
        {
          "id": 2531,
          "rider_item_id": 867,
          "equipment_category_id": 3994,
          "equipment_item_ids": [
            1,
            2,
            3
          ],
          "quantity": 4,
          "created_at": "2016-09-23T11:30:03.874+03:00",
          "updated_at": "2016-09-23T11:30:03.874+03:00"
        }
      ]
    }
  ],
  "meta": {
    "pagination": [
      {
        "current_page": 0,
        "next_page": 3,
        "prev_page": 1,
        "total_pages": null,
        "total_count": ""
      }
    ]
  }
}

Generated MSON:

## `rider_item_variant` (object)

- `id`: `2531`  (number)
- `rider_item_id`: `867`  (number)
- `equipment_category_id`: `3994`  (number)
- `equipment_item_ids` (array[number])
- `quantity`: `4`  (number)
- `created_at`: `2016-09-23T11:30:03.874+03:00`  (string)
- `updated_at`: `2016-09-23T11:30:03.874+03:00`  (string)

## `rider_item` (object)

- `id`: `867`  (number)
- `artist_program_id`: `1742`  (number)
- `created_at`: `2016-09-23T11:30:03.863+03:00`  (string)
- `updated_at`: `2016-09-23T11:30:03.863+03:00`  (string)
- `rider_item_variants` (array[rider_item_variant])

## `pagination` (object)

- `current_page`: `0`  (number)
- `next_page`: `3`  (number)
- `prev_page`: `1`  (number)
- `total_pages` (object)
- `total_count` (string)

## `meta` (object)

- `pagination` (pagination)

MSON: nullability of data structures handled differently from built-in types?

If I define the following spec on Apiary.io:

FORMAT: 1A
HOST: http://polls.apiblueprint.org/

# Test

## Root [/]

### Get Everything [GET]

+ Response 200 (application/json)
    + Attributes
        + example1 (string, optional, nullable) - An optional nullable string
        + example2: value (string, optional, nullable) - An optional nullable string with a sample value

+ Response 201 (application/json)
    + Attributes
        + example1 (Example, optional, nullable) - An optional nullable Example
        + example2: value (string, optional, nullable) - An optional nullable string with a sample value

# Data Structures

## Example
+ title (optional, nullable)
+ description (optional, nullable)

then I see the generated response structures below:

Response 200

{
  "example1": null,
  "example2": "value"
}

Response 201

{
  "example1": {
    "title": null,
    "description": null
  },
  "example2": "value"
}

I expected the second response structure to match that of the first response.

If I update my Data Structure section to:

# Data Structures

## Example
+ title (optional)
+ description (optional)

then the generated response for status code 201 becomes

{
  "example1": {},
  "example2": "value"
}

Again, I would have expected this to match the structure of the status code 200 response. What am I not understanding here?

Unclear spec on array[number, string]

In https://github.com/apiaryio/mson/blob/master/MSON%20Specification.md#351-type-specification, there's sentence

Indicates a array type structure MAY include distinct numbers or strings as values.

Does the "MAY" mean

  • that the array can contain anything and strings and values are just hints
  • or that the array can contain ONLY strings and values?

If you're going to change the wording, please also mind the Indicates a array part should probably be correctly written as Indicates an array.

Empty ENUM included in Schema

I'm struggling to find a data structure syntax that generates JSON schema from MSON that I can use effectively with Dredd.

My data structure is as follows:

## Nation (object)

+ id (string) Zid for Nation
+ type (string) The object type that this data represents
+ label (string) Name of nation
+ languages (array[Language], fixed) The languages available within this Nation
+ years (array[Year], fixed) The years available within this Nation

## Year (object)
+ id (string) Zid for Nation
+ type (string) The object type that this data represents
+ label (string) The name of the year group

## Language (object)
+ id (string) Zid for Language
+ type (string) The object type that this data represents
+ label (string) The name of the supported language
+ code (string) The code for the supported language

But when the resulting JSON-schema includes an empty enum property that causes my test to fail due to the

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "enum": [
              ""
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              ""
            ]
          },
          "label": {
            "type": "string",
            "enum": [
              ""
            ]
          },
          "languages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "enum": [
                    ""
                  ]
                },
                "type": {
                  "type": "string",
                  "enum": [
                    ""
                  ]
                },
                "label": {
                  "type": "string",
                  "enum": [
                    ""
                  ]
                },
                "code": {
                  "type": "string",
                  "enum": [
                    ""
                  ]
                }
              },
              "required": [
                "id",
                "type",
                "label",
                "code"
              ],
              "additionalProperties": false
            }
          },
          "years": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "enum": [
                    ""
                  ]
                },
                "type": {
                  "type": "string",
                  "enum": [
                    ""
                  ]
                },
                "label": {
                  "type": "string",
                  "enum": [
                    ""
                  ]
                }
              },
              "required": [
                "id",
                "type",
                "label"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "id",
          "type",
          "label",
          "languages",
          "years"
        ],
        "additionalProperties": false
      }
    },
    "meta": {
      "type": "object",
      "properties": {}
    }
  },
  "required": [
    "data"
  ]
}

This empty enum results in my tests failing as the data returned from my API doesn't match it.

Not sure if I've misinterpreted the documentation or if this is a genuine bug.

Allow to generate `title` key in JSON Schema

It would be great to be able to specify a title property with the schema for instance with:

# Test

 - something (string) - # Why not a Title! - As well as a description

Would generate

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "something": {
      "type": "string",
      "title": "Why not a Title!",
      "description": "As well as a description"
    }
  }
}

Allowing to implement root level title (which is connected to #70) and descriptions would also fit idiomatic JSON Schema.

It seems that this is connected to a number of issues which are about using MSON to generate expressive JSON Schema (#43, #69, #70). It might be good to document the subset of JSON Schema that MSON covers (to help both inform those who might be interested in this approach, and maybe feed a roadmap?).

Allows MSON obejcts to have a description

Currently when defining an MSON object you need to do something like the following:

## User (object)
+ email (string, required) - the email of the user
+ name (string, required) - the user's name

Which lets you describe the elements of the object, but not the object overall. It would be handy to be able to have the ability to add a description for the object, perhaps like this:

## User (object)
Represents a user of the system.
+ email (string, required) - the email of the user
+ name (string, required) - the user's name

This is a really trivial example, and I'd likely not do it for such an obvious object, however, for more domain specific objects, this would help a lot with understanding.

I bring this up simply because I did this in a Data Structure section on apiary.io and my api's that were referring were simply showing empty objects. Once I removed the descriptions, things started showing as expected.

Ideally this support would be added in to the Spec. Alternatively, since this seems to not be allowed in the spec currently, an error should have showed up telling me this was invalid.

dereference particular attribute of MSON model

I find myself wanting to just dereference particular attributes of models while working on things, rather than say including the whole model (this probably relates to api-blueprint-rfcs#3). There are two cases, in particular where this is coming up. I tried to see if there was some way to do this I was missing, but didn't have luck finding anything.

I imagine this might look something like Resource[attribute], similar to the array[type] syntax, but I don't really have strong feelings in particular about the specifics.

  1. I'd like to include only a subset as attributes for requests to create . For example, created_at/updated_at and uuid are part of the data model, but are usually assigned rather than passed in the request.
  2. I'd like to be able to refer to a different data models keys, in particular for exposing foreign keys.

In both cases, it is really just a subset (or single) attribute that I want to be able to pull in, rather than duplicating the definition. Both cases mirror how I've done this in pure json-schema via prmd before, fwiw.

Hope that is relatively clear, but do let me know if you have questions or I can further clarify. Thanks!

How to express an object whose keys are ids?

I can't see how to specify:

  • an object with variable keys
  • the type of an object keys (can only name a key, giving it a string type)

I want to describe a response that looks like

{
    1: (UserObject),
    2: (UserObject),
}

etc, where the keys are ids

how to specify multiple types for a property?

When working with polymorph types, a property could have a set of possible types.

## BasketItemRule
+ discountOperation: (AbsoluteBasketItemDiscountOperation, RelativeBasketItemDiscountOperation)
+ selectors: (array[BasketItemSelector])

In this case the discountOperation can either have an AbsoluteBasketItemDiscountOperation or an RelativeBasketItemDiscountOperation.

For arrays I found somewhere in the documentation the following syntax

foobar: (array[A, B])

to accept elements of type A or type B

Behaviour when redefining attributes in Mixins

Not sure if this is the right repo to talk about this, as it probably also relates to implementations. It seems like the behaviour when redefining attributes via Mixins is not defined at all. I have included the MSON I am talking about at the bottom of this to make it more readable.

Basically, I have two mixins which define the same attribute and its value is an object. My naive expectation (or maybe hope) was that the two object values would get merged, so that I would have one JSON dictionaries with values and keys of both those objects in the resulting JSON representation. What actually happens is that the value from the second mixin overwrites the first.

Is this considered to be the correct behaviour? If yes, is there a way to achieve the merging that I naively expected?

My MSON:

### Content Type

- sys
    - type: ContentType - Type of Resource
    - id: 3ORKIAOaJqQWWg86MWkyOs - Identifier
    - version: 1 (number) - Version of Resource

### Content Type Creation

- name: Blog Post - Name of the Content Type
- fields (array[object]) - Defined Fields
    - (object)
        - id: title - Identifier of the Field
        - name: Title - Display name of the Field
        - type: Text - Type of the Field
    - (object)
        - id: body - Identifier of the Field
        - name: Body - Display name of the Field
        - type: Text - Type of the Field

### Content Type Published

- Include Content Type Creation
- Include Content Type
- Include Resource Published

### Resource Published

- sys - System Attributes
    - firstPublishedAt: `2015-05-15T13:38:11.311Z` - Date/time of first publishing
    - publishedCounter: 2 (number) - Number of times published
    - publishedAt: `2015-05-15T13:38:11.311Z` - Date/time of current publishing
    - publishedBy (User B)
    - publishedVersion: 9 (number) - Version of the resource that has been published

Resulting JSON:

{
  "name": "Blog Post",
  "fields": [
    {
      "id": "title",
      "name": "Title",
      "type": "Text"
    },
    {
      "id": "body",
      "name": "Body",
      "type": "Text"
    }
  ],
  "sys": {
    "firstPublishedAt": "2015-05-15T13:38:11.311Z",
    "publishedCounter": 2,
    "publishedAt": "2015-05-15T13:38:11.311Z",
    "publishedBy": {
      "sys": {
        "type": "Link",
        "linkType": "User",
        "id": "4FLrUHftHW3v2BLi9fzfjU"
      }
    },
    "publishedVersion": 9
  }
}

Desired JSON:

{
  "name": "Blog Post",
  "fields": [
    {
      "id": "title",
      "name": "Title",
      "type": "Text"
    },
    {
      "id": "body",
      "name": "Body",
      "type": "Text"
    }
  ],
  "sys": {
    "firstPublishedAt": "2015-05-15T13:38:11.311Z",
    "publishedCounter": 2,
    "publishedAt": "2015-05-15T13:38:11.311Z",
    "publishedBy": {
      "sys": {
        "type": "Link",
        "linkType": "User",
        "id": "4FLrUHftHW3v2BLi9fzfjU"
      }
    },
    "publishedVersion": 9,
    "type": "ContentType",
    "id": "3ORKIAOaJqQWWg86MWkyOs",
    "version": 1
  }
}

invalid value format for 'number' type

I'm getting the error:

[BS] File changed: .tmp/blueprint.apib
>> Line 0: invalid value format for 'number' type. please check mson specification for valid format (warning code 4)
>> Context

With the following markdown:

+ Response 200 (application/vnd.api+json)

    Received on successful update or insert.

    + Attributes
        + posts (array)
            + name: Apiary
            + founded: 2011 (number) - The year in which the company was founded

sets

How about having sets, which is really just arrays that can have predefined values at most one time?

Proposed syntax:

+ privileges (set[string], required)
    + network
    + mailman
    + procmod
    + procview
    + lpadmin
    + lpoperator

Any JSON to MSON converters?

I don't see mention of any.

I also don't know what exactly is the motivation of this project, but I see a converter (or transpiler, I don't know the correct term) like this being very useful for, for example, storing structured data you already have in markdown environments, like Trello and others.

[question] Using MSON in JSDoc

What is the best way to use MSON to document object parameter structure?

I.e. use short instead of long description:

@param {Object}   my                            My object
@param {Object}   my.SubObject           My  subobject
@param {String}   my.SubObjectFiled1  My  subobject field 1

P.S. This function has no unit tests yet.

Anonymous non-uniform property?

How can I define a (named) Attribute for this structure?

I'm documenting an API that, at one point, returns something like this:

{
    "tag1" : [ 1, 2, 3],
    "tag2" : [2, 4, 6, 8],
    "tag3" : [1, 1, 2, 3, 5, 8, 13]
}

But not quite like that: on any given call, depending on the app state, there might or might not be values for any given tag. If a given tag has no values, then it's entirely suppressed (no empty sub-array or null value). So this, also, is a possible return:

{
    "tag2" : [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5],
    "tag3" : [3, 4, 5]
}

And likewise all of the other subsets.

To top it all off, that set of tags is useful in its own right (e.g., as an URI Template Parameter for "just give me any tag2 values").

There's a hauntingly inviting section in the MSON book, Non-uniform Property, but it seems to require me to name the non-uniform entity. But it has no other name than "+ Body", and Blueprint seems to require an URL associated with every Asset definition.

Not be able to escape bashslash for fixed value

I tried to run "dredd get-one-post.apib http://jsonplaceholder.typicode.com/" with below blueprint with mson, but it failed.

FORMAT: 1A

# Fake Online REST API

## Group Posts

### /posts/1

#### Retrieve one post [GET]

+ Relation: posts-getposts

+ Response 200 (application/json; charset=utf-8)

    OK

    + Attributes
        - userId: 1 (number, fixed)
        - id: 1 (number, fixed)
        - title: `sunt aut facere repellat provident occaecati excepturi optio reprehenderit` (fixed)
        - body: quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto (fixed)

This seems to be mson's issue because I tried same command with blueprint with generated schema and it worked.

FORMAT: 1A

# Fake Online REST API

## Group Posts

### /posts/1

#### Retrieve one post [GET]

+ Relation: posts-getposts

+ Response 200 (application/json; charset=utf-8)

    OK

    + Schema
            {
              "$schema": "http://json-schema.org/draft-04/schema#",
              "type": "object",
              "properties": {
                "userId": {
                  "type": "number",
                  "enum": [
                    1
                  ]
                },
                "id": {
                  "type": "number",
                  "enum": [
                    1
                  ]
                },
                "title": {
                  "type": "string",
                  "enum": [
                    "sunt aut facere repellat provident occaecati excepturi optio reprehenderit"
                  ]
                },
                "body": {
                  "type": "string",
                  "enum": [
                    "quia et suscipit\\nsuscipit recusandae consequuntur expedita et cum\\nreprehenderit molestiae ut ut quas totam\\nnostrum rerum est autem sunt rem eveniet architecto"
                  ]
                }
              },
              "required": [
                "userId",
                "id",
                "title",
                "body"
              ]
            }

String varaibles?

Hello! I'm trying to create some sort of variable which holds a value.

In this case I would like a string variable which will always contain the same value.

//...more stuff up here
+ Response 401 (application/vnd.api+json)

    Received on invalid/unauthorized JWT token.

    + Attributes (object)
        + errors (array[Incorrect Credentials])
# Data Structures

## Incorrect Credentials (string) 
    - `Insufficient privileges.`

As you can see I'm trying to create a string with the value Insufficient privileges. and then use this in a response inside an array. The documentation doesn't really show an example of how to do this so I'll ask here.

fixed has too many meanings

According to MSON:

fixed - instance of this type structure and values are fixed

It's reasonable for fixed value must have fixed type structure.

However, according to test sample of boutique.js which converts AST(generated from MSON) to json-schema:

https://github.com/apiaryio/boutique.js/blob/d881db46b61de6ca0c5942d1533a6f29e7a64d92/test/formats/

- tags (array)
    - *5* (number, fixed)

is considered(in json-schema)

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "tags": {
      "type": "array",
      "items": {
        "type": "number"
      }
    }
  }
}

while

- tags (array)
    - *5* (number)

is considered(in json-schema)

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "tags": {
      "type": "array"
    }
  }
}

Because position of boutique.js in drafter.js there is a de facto standards not well documented:

fixed member types of array means array MUST have member of these type.

It's still reasonable after carefully thinking but there is no examples except the test sample of boutique.js, which make it rarely known by users.

I propose an example for this grammar in specification.

On the other hand, there is a problem drawn in with this grammar.
For example:

# Special Case

I'd like to have an array whose member is limited to specific object but this object should not be fixed.

# Some Resource [/]

## Result not perfect [GET]

+ Response 200 (application/json)
    + Attributes (array)
        + (object, fixed) - object with only attributes `a` and `b` are allowed
            + a (string)
            + b (int)

## Result also not perfect [GET]

+ Response 200 (application/json)
    + Attributes (array)
        + (object) - this mean no limitation to the members of the array
            + a (string, required)
            + b (int, required)

MSON parsing bug on apiary.io

# Data Structures

## Session Object
- links
  - self: https://example.com/session (enum)
- data
  - id: abc123 (string)
  - type: session (enum)
  - Include Account Relationship

## Account Relationship Object
- relationships
  - account
    - links
      - related: https://example.com/session/account (enum)
    - data
      - id: abc1234
      - type: account (enum)

Parses to

{
  "links": {
    "self": "https://example.com/session"
  },
  "data": {
    "id": "abc123",
    "type": "session",
    "relationships": {
      "account": null,
      "links": {
        "related": "https://example.com/session/account"
      },
      "data": {
        "id": "abc1234",
        "type": "account"
      }
    }
  }
}

See the "account": null part, that’s odd. I expected

{
    "links": {
        "self": "https://example.com/session"
    },
    "data": {
        "id": "abc123",
        "type": "session",
        "relationships": {
            "account": {
                "links": {
                    "related": "https://example.com/session/account"
                },
                "data": {
                    "id": "abc1234",
                    "type": "account"
                }
            }
        }
    }
}

Array consisting of specified types only

Hi,
we are struggling with defining MSON, which would describe array consisting of specified types only (we'd like to have included section of our json api (http://jsonapi.org/) responses fully validated by dredd).

So far, we tried this:

## Type1 (object, fixed-type)
+ prop1: `val1` (string)

## Type2 (object, fixed-type)
+ prop2: `val2` (string)

...

+ Response 200 (application/json)
    + Attributes
        + included (array, fixed-type)
            + (Type1)
            + (Type2)

Generated json schema validates this json:

{
  "included": [
    {
      "prop1": ""
    },
   {
      "prop2": ""
    }
  ]
}

but not this one:

{
  "included": [
    {
      "prop1": ""
    },
    {
      "prop1": ""
    },
   {
      "prop2": ""
    }
  ]
}

Another try was something like this:

## Type1 (object, fixed-type)
+ prop1: `val1` (string)

## Type2 (object, fixed-type)
+ prop2: `val2` (string)

...

+ Response 200 (application/json)
    + Attributes
        + included (array, fixed-type)
            + (enum)
                + (Type1)
                + (Type2)

But this seems to generate invalid json schema...

Are we missing something?
Thanks in advance!

What is the benefit of having many ways to express the same?

These two Blueprints, well MSON descriptions produce the very same result and I am wondering why there are two ways of describing the same thing. What's the rationale, wouldn't the language benefit from being simpler and in a sense more rigid? I feel that it makes the life worse as I can mix the stuff and make it even harder to read. Having just one way of doing things means less cognitive load, lower complexity in parsing and therefore less buggy tools.

# Data Structures

## A
+ x
+ y
    + z
# Data Structures

## A

## Properties
+ x
+ y
  + Properties
      + z

array samples?

I've tried to do something like:

+ tags: example (array[string]) - a set of string values

But the examples I see in the docs/inspector stuff are all just empty arrays. I tried to find other examples or explanations of this, but got a bit stuck. Would appreciate any insight about how to fix this. Thanks!

Support more primitive types (float, integer...)

As I can see on the documentation MSON only supports boolean, string and number.

Is there any change to support more primitive types?
For example, JSON Schema supports integer which MSON doesn't.

Bug in Schema generation for Enum and Array

I have an enum of strings called Notification Type
I want to another object to have a property and the properties type is an array of Notification Type.

## Notification Type (enum[string])
+ TYPE_A
+ TYPE_B
+ TYPE_C

## Notifications (object)
+ sms (array[Notification Type])
+ email (array[Notification Type])

or possibly

## Notification Type (enum[string])
+ TYPE_A
+ TYPE_B
+ TYPE_C

## Notifications (object)
+ sms (array)
    + TYPE_A (Notification Type)
    + TYPE_B (Notification Type)
+ email (array)
    + TYPE_C (Notification Type)

Basically I want the generated schema to look like this:

"notifications": {
  "email": {
    "type": "array",
    "items": {
      "type": "string",
      "enum": ["TYPE_A", "TYPE_B", "TYPE_C"]
    }
  },
  "sms": {
    "type": "array",
    "items": {
      "type": "string",
      "enum": ["TYPE_A", "TYPE_B", "TYPE_C"]
    }
  },
}

However when I try the first two options I get a schema that looks like this:

"notifications": {
  "type": "object",
  "properties": {
    "sms": {
      "type": "array",
    },
    "email": {
      "type": "array",
    }
  }
}

Adopting JSON API v1 spec

Are there any plans for improved support for the JSON API spec? It would be awesome if I could simply specify a resource by its attributes and then get a generated JSONAPI v1 compliant schema for the common REST operations from Apiary.

It's 'its'.

The possessive neuter pronoun is spelled its.
The contraction of "it is" is spelled it's.

PR to follow.

Incorrect example for array of arrays

The example in https://github.com/apiaryio/mson#array-of-arrays is (probably?) incorrect, because given MSON is object and not top-level array. Resulting AST is something like this according to existing experimental implementation (there's top-level object with one property and that property has no name.literal):

{
  "name": {...},
  "sections": [
    {
      "type": "member",
      "content": [
        {
          "type": "property",
          "content": {
            "name": {
              "variable": {}
            },
            "valueDefinition": {...}
            },
            "sections": [...]
          }
        }
      ]
    }
  ]
}

First example in https://github.com/apiaryio/mson#array-of-mixed-types is probably right as it has an object as top-level structure, but the second looks suspicious, too.

Filing an issue first instead of PR, becasue I want to check whether I'm actually right :) @zdne @pksunkara

  1. In case I'm right, we should fix the example.
  2. Parser should warn / throw errors. Property with no name shouldn't be on standard output (however, that would be a new issue for Snow Crash, it doesn't belong here).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.