Skip to content
Jørn Wildt edited this page Jun 10, 2015 · 17 revisions

The simplest possible Mason document is a JSON object with nothing but raw API data. Such a document is indistinguishable from a plain JSON object API response except for the HTTP header "Content-Type" which should be set to application/vnd.mason+json:

200 OK
Content-Type:  application/vnd.mason+json

{
  // Classic API data
  "ID": 1,
  "Title": "Program crashes when pressing ctrl-p",
  "Description": "I pressed ctrl-p and, boom, it crashed.",
  "Severity": 5
}

The @meta element

The simplest Mason element is probably the @meta element which conveys information to the client developers (and only them, not the end users!). The @meta element has a @title and a @description property for the purpose of describing the response to the client developers:

{
  // Classic API data
  "ID": 1,
  "Title": "Program crashes when pressing ctrl-p",
  "Description": "I pressed ctrl-p and, boom, it crashed.",
  "Severity": 5,

  // Additional Mason data
  "@meta": {
    "@title": "Issue",
    "@description": "This resource represents a single issue with its data and related actions."
  }
}

The @meta element may even contain links for the client developers - for instance to online documentation.

Here is a live example: http://mason-issue-tracker.azurewebsites.net/resource-common

Links

The most well known hypermedia element is probably the link which represents a relationship between the current resource and another resource. The relationship between the two resources is assigned a name (relationship type) which is used by the client to locate the link. In Mason we combine both links and other hypermedia control elements into a single object and use the link relationship type as the indexer:

{
  // Classic API data
  "ID": 1,
  "Title": "Program crashes when pressing ctrl-p",
  "Description": "I pressed ctrl-p and, boom, it crashed.",
  "Severity": 5,

  // Mason meta data
  "@meta": {
    "@title": "Issue",
    "@description": "This resource represents a single issue with its data and related actions."
  },

  // Links - and other hypermedia control elements
  "@controls": {
    "self": {
      "href": "http://issue-tracker.org/mason-demo/issues/1"
    },
    "up": {
      "href": "http://issue-tracker.org/mason-demo/projects/1",
      "title": "Containing project"
  }
}

Here is a live example: http://mason-issue-tracker.azurewebsites.net/resource-common

Each entry in the @controls object holds only one link. If more (alternative) links are available for the same link relationship then these can be added as an array of link objects in the property "alt" of the original link object:

"@controls": {
  // Primary link for "contact"
  "contact": {
    "href": "...",
    "title": "Contact information",
    "type": "application/vnd.mason+json",

    // Alternate links for "contact"
    "alt": [
      {
        href: "...",
        "title": "Contact information (in vCard)",
        "type": "text/vcard"
      }
    ]
  }
}

The use of the "alt" property is an attempt to solve one of the debated features of HAL: links as either arrays or single objects. In HAL it is possible to represent links as either an array of links or a single link object. This has caused some debate because the client has to check for the type of the link element at runtime. With Mason's approach the client can safely decode links as objects, always, and if it is interested in alternate types of the link then it can check the "alt" property.

If you want to read more about why links are good then try this: http://soabits.blogspot.dk/2013/12/selling-benefits-of-hypermedia.html

Minimized responses

Some of the Mason elements are only relevant for client developers exploring the API (for instance the @meta element). These elements can be removed by the server at runtime to reduce the size of the payload and thus save some bandwidth.

The recommended way of instructing the server to return a minimal response is to pass the value "representation=minimal" in the "Prefer" header.

Namespaces and curies

Link relations (or rather "control names") are either simple well known names registered in the IANA link relation registry - or a URI (see http://tools.ietf.org/search/rfc5988#section-4.2). The use of URIs for additional link relations can cause some confusion because a link may have two URIs in it (the link relation and the target URI). To improve human readability of the format (and reduce the payload slightly) Mason introduces the concept of namespaces:

"@namespaces": {
  "is": {
    "name": "http://issue-tracker-reltypes.org/rels#"
  }
}

A namespace declaration couples a prefix ("is" in the above example) with a URI. This prefix can then be used in link relations followed by a colon and a "reference" to create a so called Curie (see http://www.w3.org/TR/2009/CR-curie-20090116/):

{
  "@namespaces": {
    "is": {
      "name": "http://issue-tracker-reltypes.org/rels#"
    }
  },

  "@controls": {
    // Curie link relation
    "is:attachments": {
      "href": "...",
      "title": "List of attachments"
    },
    // Non standard link relation
    "http://issue-tracker-reltypes.org/rels#attachments": {
      "href": "...",
      "title": "List of attachments"
    },
    // Standard, non curie, link relation
    "up": {
      "href": "...",
      "title": "Containing project"
  }
}

Curies are resolved to URIs by concatenation of the expanded URI and the reference.

Other hypermedia elements

Mason also supports more complex hypermedia elements such as templated links and actions (AKA "forms" for APIs).

A link template can be expanded to a real URI based on one or more template variables as described in RFC 6570 - URI Templates.

Here is an example showing how to represent a link template for querying an issue tracker:

"@controls": {
  "is:issue-query": {
    "href": "http://issue-tracker.org/mason-demo/issues-query?text={text}&severity={severity}&project={pid}",
    "isHrefTemplate": true,
    "title": "Search for issues",
    "description": "This is a simple search that do not check attachments."
  }
}

Here is a live example: http://mason-issue-tracker.azurewebsites.net/resource-common.

More complex actions like for instance "Update issue X with values A,B,C" can also be declared in the control element. Here is one such example that instructs the client about how to update an issue from a issue tracker:

"@controls": {
  "is:issue-update": {
    "title": "Update issue details",
    "encoding": "json",
    "href": "http://issue-tracker.org/mason-demo/issues/1",
    "method": "POST",
    "template": 
    {
        "Title": "Crash after payment",
        "Description": "I have justed paid for two pairs of shoes - or rather I tried to. When I clicked 'Pay' all I got was a yellow error screen.",
        "Severity": 3
    }
  }
}

The control element above tells the client that 1) it should use JSON to encode the update data when sending it, 2) it should POST the data to the URL specificed by "href" and 3) it may use the data in "template" as default values for the update.

Error handling

Mason reserves the element @error for error information:

"@error": {
  "@id": "b2613385-a3b2-47b7-b336-a85ac405bc66",
  "@message": "There was a problem with one or more input values.",
  "@code": "INVALIDINPUT",
  "@messages": [
    "title should not be null, and empty string or consists only of white-space characters..\r\nParameternavn: title"
  ]
}

The @id value is a unique value (for instance a GUID) identifying this exact error. This can help locating the corresponding entries in logfiles. The @message value is an error message appropriate for displaying to the end users. Further messages for the end user can be listed in the @messagesarray.

Error elements may also contain links and detailed information to the client developers.

See http://soabits.blogspot.dk/2013/05/error-handling-considerations-and-best.html for some background on these choices.