An intuitive JSON-based hypermedia type for REST.

Abstract

This document specifies the Ion Hypermedia Type, a simple and intuitive JSON-based hypermedia type for REST.

Status

This Internet-Draft is a working document of the Ion Working Group (IWG). Note that other groups may also distribute working documents as Internet-Drafts.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."

This Internet-Draft will expire on 31 September 2017.

Copyright Notice

Copyright (c) 2013-2017 Ion Working Group and persons identified as document authors. All rights reserved.

1. Introduction

HTTP is commonly used to transfer data in many different data formats. With the advent of the REST architectural style and the success of the JavaScript programming language, HTTP-enabled applications regularly support JSON as a preferred format for data exchange.

However, this poses a challenge for machine data exchange at web scale across heterogeneous domains and organizations; JSON’s simple grammar can support virtually any data model - additional context is required for machine clients and servers to automate information discovery and exchange via hypermedia controls.

Ion codifies specific name/value pairs within JSON objects to help automate JSON-based hypermedia interchange between machines. And while machine data and metadata interchange is the primary goal, Ion’s second most important design goal is to enable intuitive and context-relevant structure so Ion content is very easy to understand for humans, even if they may not know what Ion is.

1.1. Terminology

These terms are defined by this specification:

Member

A JSON name/value pair as defined in RFC 7159.

Root Object

The single JSON object at the root of an Ion content structure.

Value Object

A JSON object with a member named value.

Collection Object

A Value Object where the value member is a JSON array. If a JSON value is an element in a Collection Object's value array, it is said that the Collection Object contains that value.

Resource

The referent of an International Resource Identifier.

Collection Resource

A Resource that is also a Collection Object.

Link

A JSON object with an IRI member named href. This is Ion’s JSON serialization of a Web Link that enables linking from one resource to another.

Form Field

A JSON object with members that describe a named value that may be collected and submitted to a linked resource location.

Form Field Option

A Value Object with a value that may be applied to the containing Form Field’s value.

Form

An Collection Object where the value array member contains Form Fields.

Linked Form

A Form that is also a Link. Form data submitted will be sent to the form’s href resource location.

File Object

A Value Object where the value member is a Base64URL-encoded byte array that also has mimetype and name members representing file metadata.

1.2. Media Type Name and Version

The Media Type name assigned for Ion content is:

application/ion+json

This format may be referred to as "Ion 1.0". This specification uses "Ion" internally.

Any future version will be represented with a media type parameter named v with a semantic version value. For example (non-normative):

application/ion+json;v=2

1.3. Examples

All following examples are non-normative.

1.3.1. Example Objects

JSON objects are parsed as as expected:

Example JSON Object
{
  "firstName": "Bob",
  "lastName": "Smith",
  "birthDate": "1980-01-23"
}

A Value Object is a JSON object with a value member:

Example Value Object
{
  "value": "Hello"
}

A Value Object exists to represent a primary JSON value, but it also might have other members that are contextually relevant to the value. For example, one might add a lang member to indicate a spoken language:

Example Value Object With Supporting Members
{
  "value": "Hello",
  "lang": "en"
}

An Ion Link is a JSON object that contains an IRI member named href. An Ion Link is a JSON serialization of a web link to another resource.

For example, assume that someone named "Joe" is an employee of the "Acme" corporation. A link within the "Joe" resource to Joe’s employer might be represented as follows:

Ion Link from one resource to another:
{
  "name": "Joe",
  "employer": { "href": "https://example.io/corporations/acme" }
}

1.3.3. Example Collections

A Collection Object is a Value Object where the value member is a JSON array:

Example Empty Collection Object:
{
  "value": []
}

What’s the point of this? Why not just use a JSON array directly?

The reason is that other members within the Collection Object may provide additional contextual information about the value array itself or the elements in the value array, something not possible with a direct array.

For example, a Collection Object could have an eform ("element form") member to represent the structural 'form' of each element in the value array instead of repeating this information in every array element:

Example Collection Object With element metadata:
{
  "eform": { "href": "https://example.io/users/form" },
  "value": [
      {
        "firstName": "Bob",
        "lastName": "Smith",
      },
      {
        "firstName": "Jane",
        "lastName": "Doe",
      }
    ]
}

Collection Objects can have other members to build up rich functionality. For example, one can add link members to represent a Collection Object as an IRI-accessible Collection Resource:

Example Empty Collection Resource:
{
  "self": { "href": "https://example.io/users", "rel": ["collection"] },
  "value": []
}

More members can be added to build up rich functionality. For example, a Collection Resource with discoverable pagination:

Example Paginated Collection Resource:
{
  "self": { "href": "https://example.io/users", "rel": ["collection"] },
  "desc": "Showing 25 of 218 users.  Use the 'next' link for the next page.",
  "offset": 0,
  "limit": 25,
  "size": 218,
  "first": { "href": "https://example.io/users", "rel": ["collection"] },
  "previous": null,
  "next": { "href": "https://example.io/users?offset=25", "rel": ["collection"] },
  "last": { "href": "https://example.io/users?offset=200", "rel": ["collection"] },
  "value": [
    {
      "self": { "href": "https://example.io/users/1" },
      "firstName": "Bob",
      "lastName": "Smith",
      "birthDate": "1977-04-18"
    },
    //... items 2-24 omitted for brevity
    {
      "self": { "href": "https://example.io/users/25" },
      "firstName": "Jane",
      "lastName": "Doe",
      "birthDate": "1980-01-23"
    }
  ]
}

1.3.4. Example Form

An Ion Form is a Collection Object where the value member array contains Form Fields. Ion Forms ensure that resource transitions (links) that support data submissions can be discovered automatically (colloquially referred to as HATEOAS).

Example Ion Form
{
  "href": "https://example.io/users", "rel":["create-form"], "method": "POST",
  "value": [
    { "name": "username" },
    { "name": "password", "secret": true },
    { "name": "favoriteColor", "label": "Favorite Color", "options": {
        "value": [
          { "label": "Red", "value": "red" },
          { "label": "Blue", "value": "blue" }
        ]
      }
    },
    { "name": "visitedContinents", "type": "set", "minsize": 1, "maxsize": 7, "options": {
        "value": [
          { "label": "Africa", "value": "af" },
          { "label": "North America", "value": "na" },
          { "label": "South America", "value": "sa" },
          { "label": "Europe", "value": "eu" },
          { "label": "Asia", "value": "as" }
          { "label": "Oceania", "value": "oc" }
          { "label": "Antarctica", "value": "an" }
        ]
      }
    },
    { "name": "favoriteContinent", "options": {
        "value": [
          { "label": "Africa", "value": "af" },
          { "label": "North America", "value": "na" },
          { "label": "South America", "value": "sa" },
          { "label": "Europe", "value": "eu" },
          { "label": "Asia", "value": "as" }
          { "label": "Oceania", "value": "oc" }
          { "label": "Antarctica", "value": "an" }
        ]
      }
    }
  ]
}

1.4. Notational Conventions

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described RFC2119 when they appear in UPPERCASE. If these words are used without being spelled in uppercase then they are to be interpreted with their normal natural language meanings, without any normative meaning.

2. Content Structure

Ion content MUST use UTF-8 encoding. Other encodings MUST NOT be used.

Ion content MUST have exactly one root JSON object, called the Root Object. The Root Object MAY contain name/value pairs called 'members' and any level of nested JSON objects.

3. Value Objects

A Value Object is a JSON object that contains a value member.

A Value Object is used to represent a primary JSON value but also allows for other peer members to provide additional contextual information or metadata regarding the value member.

An Ion parser MUST identify a JSON object as a Value Object if the JSON object contains a JSON member with a name equal to the case-sensitive octet sequence value.

A Value Object MAY have additional members other than the value member.

The member names within an identified Value Object SHOULD be unique; Ion parsers MUST either reject Value Object members with duplicate member names or use a JSON parser that returns only the lexically last duplicate member, as specified in Section 15.12.2 (The JSON Object - parse) of ECMAScript 5.1.

An Ion Parser:

  1. MUST recognize all members defined in the Ion Object Member Registry,

  2. MAY recognize members which are not defined in the Ion Object Member Registry,

  3. MUST ignore members which it does not understand.

Consider the following non-normative example of an object with a greeting member:

Example object with a greeting:
{
  "greeting": "Hola"
}

In this example, the greeting member value is a Spanish language word. A Value Object might be used instead to represent additional contextual information that might be relevant to user agents. For example:

Example object with a greeting value object:
{
  "greeting" : { "value":  "Hola", "lang": "es" }
}

In this example, the greeting member transitively reflects reflects a value of Hola through the presence of a Value Object.

4. Files

File interchange between machines often requires metadata in addition to file contents.

An Ion File Object is a Value Object that represents a file’s contents and its associated metadata.

4.1. File Object Structure

Ion parsers MUST identify any JSON object as an Ion File Object if the object contains:

  1. a non-null name string member.

  2. a non-null mediatype string member that equals a syntactically valid Media Type string value.

  3. a non-null value string member that is a base64Url-encoded octet sequence according to RFC 4648, Section 5. The string MAY be the empty string to indicate a file of zero length. A non-empty string MUST NOT contain characters that are not in the base64Url alphabet.

  4. either a type member equal to the octet sequence file or the object is in a Collection Object’s value array and the Collection Object has an etype member with a value equal to the octet sequence file.

Ion parsers MUST NOT identify a JSON object as an Ion File Object if the object does not match the above conditions.

If the Ion File Object is contained within an Ion Collection Object’s value array and the Collection Object has a member named etype with a value equal to the octet sequence file, it is RECOMMENDED to omit the type member in each object/element in the array to reduce verbosity.

A non-normative example of one file:

{
  "type": "file",
  "name": "hello.txt",
  "mediatype": "text/plain",
  "value": "SGVsbG8gd29ybGQ="
}

Because this file object is not an element within a Collection Object, the type member is required.

A non-normative example of more than one file within a Collection Object:

{
  "etype": "file",
  "value": [
    {
      "name": "hello.txt",
      "mediatype": "text/plain",
      "value": "SGVsbG8gd29ybGQ="
    },
    {
      "name": "hello2.txt",
      "mediatype": "text/plain",
      "value": "SG93IGFyZSB5b3UgdG9kYXk_"
    }
  ]
}

Because these two file objects are elements within a Collection Object that has an etype member, each element/object does not need to have a type member.

4.2. File Object Members

An Ion File Object contains one or more of the following members.

4.2.1. mediatype

The mediatype member is a JSON string that is equals a syntactically valid Media Type string value.

The mediatype member MUST NOT be null.

The use of this member is REQUIRED.

4.2.2. name

The name member is the string name of the file. This value is the unqualified file name, without path information.

The name member MUST NOT be null. If the file name cannot be determined or represented, the blank string must be used.

The use of this member is REQUIRED.

4.2.3. type

The type member represents the type of Ion object encountered. For Ion File Objects, this member, if present, MUST equal the octet sequence file.

If the Ion File Object exists as an element within a Collection Object’s value array and the Collection Object has a etype member equal to the octet sequence file, this member is OPTIONAL.

Otherwise, the use of this member in an Ion File Object is REQUIRED.

4.2.4. value

The value member value is a base64Url-encoded octet sequence according to RFC 4648, Section 5. The string MAY be the empty string to indicate a file of zero length.

The value member MUST NOT equal null.

The value MAY equal the empty string to indicate a file of zero length.

A non-empty value MUST NOT contain characters that are not in the base64Url alphabet.

The use of this member is REQUIRED.

An Ion Link is a a JSON object that contains an IRI member named href. An Ion Link is a JSON serialization of a web link to another resource.

An Ion parser MUST identify a JSON object as an Ion Link if the object contains an IRI member with a name equal to the case-sensitive octet sequence href.

If the href member value is null, not a string, an empty string, or a whitespace-only (blank) string, an Ion parser MUST NOT identify the object as an Ion Link.

An Ion Link MAY have additional members other than the href member.

A non-normative example of a minimal Ion link:

Example simplest Ion link:
{ "href": "https://example.io/corporations/acme" }

A non-normative example of an Ion Link that is also a Value Object:

Example Ion Link that is also a Value Object:
{
  "href": "https://example.io/corporations/acme",
  "value": "Acme, Inc."
}

All Ion links have one or more Link Relation Types. A link’s total set of link relation types is the set union of the link’s implicit link relation type and the link’s explicit link relation types.

All Ion links have exactly one implicit link relation type. The implicit link relation type can be one of three possible values depending on where the link is located in the Ion content:

  1. Root Object

  2. Named Link

  3. Collection Object value array element

If the Root Object is also found to be an Ion Link, it has an implicit link relation type of self.

A non-normative example of a Root Object that is also an Ion Link:

{
  "href": "https://example.io/users/1",
  "name": "Joe"
}

If a JSON Object member value is an Ion Link, the Ion Link is implicitly assigned a link relation type that equals the member name.

A non-normative example:

{
  "employer": { "href": "https://example.io/corporations/acme" }
}

The above example shows an Ion Link member named employer. The octet sequence employer is therefore assigned as the link’s implicit link relation type.

Any Ion Link in a Collection Object's value array is implicitly assigned the item link relation type.

A non-normative example:

{
  "self": { "href": "https://example.io/users", "rel": ["collection"] },
  "value": [
    { "href": "https://example.io/users/1" },
    { "href": "https://example.io/users/2" }
  ]
}

The above example has 2 Links in its value array. Each of these 2 links are implicitly assigned the item link relation type.

An Ion Link MAY have one or more explicitly defined link relation types declared as an array of strings assigned to the link Meta Object’s rel member.

A non-normative example of a link with an explicitly defined link relation type:

Example Ion Link with explicit link relation type:
{ "href": "https://cdn.example.com/example.ico", "rel": ["icon"] }

The above example has an explicit link relation type of icon.

More than one explicit link relation type MAY be defined in the rel array.

Ion parsers MUST ignore any Link rel member with value of null, not a string, an empty string, or a whitespace-only (blank) string.

6. Forms

If data can be submitted to a linked resource location, information about that data must be made available to a hypermedia client so it can collect and then submit the data.

An Ion Form represents named data values that may be submitted to a linked resource location. A JSON object of members that describe each named data value is called a Form Field. An Ion Form is then effectively a collection of form fields with additional metadata that controls how the form fields are submitted to a linked resource location.

If an Ion Form is also an Ion Link, collected data associated with the form’s fields may be submitted to the Form’s linked resource location.

An Ion Form may not be an Ion Link if and only if that form is nested inside another form or form field. Nesting forms allows for creation of complex object graphs that may be submitted to the top-most form’s linked resource location.

An Ion Form MUST also be an Ion Link if it is not nested within another form.

6.1. Form Structure

Ion parsers MUST identify any JSON object as an Ion Form if the object matches the following conditions:

  1. Either:

    1. The JSON object is discovered to be an Ion Link as defined in Section 4 AND its meta member has an internal rel member that contains one of the octet sequences form, edit-form, create-form or query-form, OR:

    2. The JSON object is a member named form inside an Ion Form Field.

  2. The JSON object has a value array member with a value that is not null or empty.

  3. The JSON object’s value array contains one or more Ion Form Field objects.

  4. The JSON object’s value array does not contain elements that are not Ion Form Field objects.

Ion parsers MUST NOT identify a JSON object as an Ion Form if the object does not match the above conditions.

A non-normative example:

{
  "href": "https://example.io/loginAttempts", "rel":["form"], "method": "POST",
  "value": [
    { "name": "username" },
    { "name": "password", "secret": true }
  ]
}

6.2. Form Fields

An Ion Form Field is a JSON object in an Ion Form’s value array that contains one or more Form Field Members.

An Ion Form Field MUST have a string member named name.

Each Ion Form Field within an Ion Form’s value array MUST have a unique name value compared to any other Form Field within the same array.

6.3. Form Field Members

An Ion Form Field contains one or more of the following members.

6.3.1. desc

The description member is a string description of the field that may be used to enhance usability, for example, as a tool tip.

Use of this member is OPTIONAL.

6.3.2. eform

The eform member value is either a Form object or a Link to a Form object that reflects the required object structure of each element in the field’s value array. The name "eform" is short for "element form".

If the field’s type member is not equal to array or set, an Ion parser MUST ignore the eform member.

If the eform member equals null, an Ion parser MUST ignore the eform member.

If the eform member is not a valid Ion Form object, an Ion parser MUST ignore the eform member.

If the eform member exists and is valid, and the etype member does not exist or equals null, an Ion parser MUST assign the field an etype member with a value of object.

If the etype member does not equal object, an Ion parser MUST ignore the eform member.

If the eform member is a Link or a Linked Form, Ion parsers MUST NOT submit data to the eform value’s linked href location. The eform’s href location may only be used to read the associated form to determine the structure of the associated form object.

If it has been determined that the eform member should be evaluated according to these rules, a validating user agent MUST ensure each element in the field’s value array conforms to the specified eform form structure before form submission.

Use of this member is OPTIONAL.

6.3.3. enabled

The enabled member indicates whether or not the field value may be modified or submitted to a linked resource location.

The enabled member is a boolean; it must equal either true or false. null or any other JSON value MUST NOT be specified.

A false value indicates that the field value MUST NOT be modified or submitted to a linked resource location.

If the enabled member is not present, or if it present and equal to true, the field may be modified or submitted a linked resource location.

If a field should be considered enabled, it is RECOMMENDED to omit the enabled member entirely to reduce verbosity.

Use of this member is OPTIONAL.

6.3.4. etype

The etype member specifies the mandatory data type of each element in a form field’s value array. The name "etype" is short for "element type".

If the field’s type member is not equal to array or set, an Ion parser MUST ignore the etype member.

If the etype member equals null and the eform member exists and is a valid Ion form, an Ion parser MUST assign the etype member a value of object.

If the etype member does not equal one of the octet sequences Ion Value Object Type Values, an Ion parser MUST ignore the etype member.

If the etype member is ignored, an Ion parser MUST NOT perform type validation on any value in the field’s value array before form submission.

If it has been determined that the etype member should be evaluated, a validating user agent MUST ensure each element in the fields values array adheres to the specified etype (and any valid eform) before form submission.

Use of this member is OPTIONAL.

6.3.5. form

The form member value is either a Form object or a Link to a Form object that reflects the required object structure of the Field value. This allows Ion content authors to define complex data/content graphs that may be submitted to a single linked resource location.

Ion parsers MUST ignore a discovered form member if the field type member does not equal object.

If the form member is a Link or a Linked Form, Ion parsers MUST NOT submit data to the form value’s linked href location. The form’s href location may only be used to read the associated form to determine the structure of the associated value object.

Where a Form contains nested Forms in this manner, the resulting collected data will form an object graph. This data/graph may only be submitted to the top-most Form’s linked resource location; Ion parsers MUST NOT submit data to any nested/child Form linked resource location.

6.3.6. label

The label member is a human-readable string that may be used to enhance usability.

Use of this member is OPTIONAL.

6.3.7. max

The max member indicates that the field value must be less than or equal to the specified max value.

The max member value MUST conform to the data type defined by the type member value; Ion parsers MUST ignore any max member where the max value does not conform to the type data type.

The max member value may only be defined when the type value is equal to number, integer, decimal, date, datetime, datetimetz, time, or timetz as defined in Ion Value Object Type Values. Ion parsers MUST ignore any max member if the type member value does not match one of these values.

If the min member is present, the max value must be greater than or equal to the min value. Ion parsers MUST ignore both the min member and the max member if the max value is less than the min value.

Use of this member is OPTIONAL.

6.3.8. maxlength

The maxlength member is a non-negative integer that specifies the maximum number of characters the field value may contain. Ion parsers MUST ignore any maxlength member that has a negative integer value.

Ion parsers MUST ignore any discovered maxlength member if the field type equals object, array, or set.

If a field has both minlength and maxlength members, the field’s minlength member value MUST be less than or equal to the field’s maxlength member value. Ion parsers MUST ignore both the minlength and maxlength members if the maxlength value is less than the minlength value.

Use of this member is OPTIONAL.

6.3.9. maxsize

The maxsize member value is a non-negative integer that specifies the maximum number of field values that may be submitted when the field type value equals array or set. Ion parsers MUST ignore any maxsize member that has a negative integer value.

If the field type value does not equal array or set, an Ion parser MUST ignore any discovered maxsize member for that field.

If a field has both minsize and maxsize members, the field’s maxsize member value MUST be greater than or equal to the field’s minsize member value. Ion parsers MUST ignore both the minsize and maxsize members if the maxsize value is less than the minsize value.

Use of this member is OPTIONAL.

6.3.10. min

The min member indicates that the field value must be greater than or equal to the specified min value.

The min member value MUST conform to the data type defined by the type member value; Ion parsers MUST ignore any min member where the min value does not conform to the type data type.

The min member value may only be defined when the type value is number, integer, decimal, date, datetime, datetimetz, time, or timetz as defined in Ion Value Object Type Values. Ion parsers MUST ignore any min member if the type member value does not match one of these values.

If the max member is present, the min value must be less than or equal to the max value. Ion parsers MUST ignore both the min member and the max member if the min value is greater than the max value.

Use of this member is OPTIONAL.

6.3.11. minlength

The minlength member is a non-negative integer that specifies the minimum number of characters the field value must contain. Ion parsers MUST ignore any minlength member that has a negative integer value.

Ion parsers MUST ignore any discovered minlength member if the field type equals object, array, or set.

If a field has both minlength and maxlength members, the field’s minlength member value MUST be less than or equal to the field’s maxlength member value. Ion parsers MUST ignore both the minlength and maxlength members if the minlength value is greater than the maxlength value.

Use of this member is OPTIONAL.

6.3.12. minsize

The minsize member value is a non-negative integer that specifies the minimum number of field values that may be submitted when the field type value equals array or set. Ion parsers MUST ignore any minsize member that has a negative integer value.

If the field type value does not equal array or set, an Ion parser MUST ignore any discovered minsize member for that field.

If a field has both minsize and maxsize members, the field’s minsize member value MUST be less than or equal to the field’s maxsize member value. Ion parsers MUST ignore both the minsize and maxsize members if the minsize value is greater than the maxsize value.

Use of this member is OPTIONAL.

6.3.13. mutable

The mutable member indicates whether or not the field value may be modified before it is submitted to the form’s linked resource location.

The mutable member is a boolean; it must equal either true or false. null or any other JSON value MUST NOT be specified.

A false value indicates that the field value MUST NOT be modified before it is submitted to the form’s linked resource location.

If the mutable member is not present, or if it present and equal to true, the field value may be modified before it is submitted to the form’s linked resource location.

If a field should be considered mutable, it is RECOMMENDED to omit the mutable member entirely to reduce verbosity.

Use of this member is OPTIONAL.

6.3.14. name

The name member is a string name assigned to the field.

The name value MUST NOT be null.

The name value MUST NOT contain only whitespace.

The name value MUST be unique compared to any other Form Field name value in the containing Form’s value array.

Use of this member is REQUIRED.

6.3.15. options

The options member is a Collection Object where the value array contains Form Field Option objects. A Form Field Option object contains one or more members defined in Form Field Option Members.

When an options member is present and the form field type does not equal set or array, any form field value specified MUST equal one of the values found within the Option array.

When an options member is present and the form field type equals set or array, the form field value MUST be a JSON array, and the array MUST NOT contain any value not found within the Option value array.

If the field type is not set or array, Ion parsers MUST ignore any option where the option value type is not the same as the field type.

6.3.16. pattern

The pattern member is a JSON string that defines a regular expression used to validate the field value.

If specified, the pattern member string value must conform to the Pattern grammar defined in Ecma-262 Edition 5.1 Section 15.10.1.

The pattern member MUST NOT be specified on fields with non-string or non-date/non-time value types.

Use of this member is OPTIONAL.

6.3.17. placeholder

The placeholder member is a short hint string that describes the expected field value.

Use of this member is OPTIONAL.

6.3.18. required

The required member indicates whether or not the field value may equal null before is submitted to the form’s linked resource location.

The required member is a boolean; it must equal either true or false. null or any other JSON value MUST NOT be specified.

A true value indicates that the field value MUST NOT equal null before it is submitted to the form’s linked resource location.

If the required member is not present, or if it present and equal to false, the field value MAY equal null before it is submitted to the form’s linked resource location.

If a field should not be considered required (i.e. optional), it is RECOMMENDED to omit the required member entirely to reduce verbosity.

Use of this member is OPTIONAL.

6.3.19. secret

The secret member indicates whether or not the field value is considered sensitive information and should be kept secret.

The secret member is a boolean; it must equal either true or false. null or any other JSON value MUST NOT be specified.

A true value indicates that the field value is considered sensitive and should be kept secret. If true, user agents MUST mask the value so it is not directly visible to the user.

If the secret member is not present, or if it present and equal to false, the field value is not considered sensitive information and does not need to be kept secret.

If a field should not be considered secret, it is RECOMMENDED to omit the secret member entirely to reduce verbosity.

Use of this member is OPTIONAL.

6.3.20. type

The type member specifies the mandatory data type that the value member value must adhere to. The type value is a string and must equal to one of the octet sequences defined in Ion data type.

If the type member is not present, an Ion parser MUST assume a default type of string for the field.

Validating Ion parsers MUST validate the value member value to ensure it adheres to the specified (or default) type before form submission.

If the type member equals array or set, and the elements in the array or set must conform to a particular type and structure, those type constraints may be defined using the etype and eform members.

Use of this member is OPTIONAL.

6.3.21. value

The value member reflects the value assigned to the field.

If the type member exists and does not equal array or set, a non-null field value value MUST conform to the data type specified by the type member value.

If the type member exists and is equal to array or set, a non-null value member value MUST be a JSON array. If the elements of the array must conform to a particular type and structure, those type constraints may be defined using the etype and eform members.

Use of this member is OPTIONAL.

6.3.22. visible

The visible member indicates whether or not the field should be made visible by a user agent. Fields that are not visible are usually used to retain a default value that must be submitted to the form’s linked resource location.

The visible member is a boolean; it must equal either true or false. null or any other JSON value MUST NOT be specified.

A false value indicates that the field MUST NOT be made visible by a user agent.

If the visible member is not present, or if it present and equal to true, the field MUST be made visible by a user agent.

If a field should be considered visible, it is RECOMMENDED to omit the visible member entirely to reduce verbosity.

Use of this member is OPTIONAL.

6.4. Form Field Option Members

An Form Field Option has one or more of the following members.

6.4.1. enabled

The enabled member indicates whether or not the Option value may be applied to the containing Form Field’s value.

The enabled member is a boolean; it must equal either true or false. null or any other JSON value MUST NOT be specified.

A false value indicates that the Option value MUST NOT be applied to the containing Form Field’s value.

If the enabled member is not present, or if it present and equal to true, the Option value may be applied to the containing Form Field’s value.

If an Option should be considered enabled, it is RECOMMENDED to omit the enabled member entirely to reduce verbosity.

Use of this member is OPTIONAL.

6.4.2. label

The label member is a human-readable string that may be used to enhance usability.

Use of this member is OPTIONAL.

6.4.3. value

The value member reflects the value assigned to the Option. An enabled Option that is selected will have its value applied to the containing Form Field’s value member.

Use of this member is REQUIRED.

6.5. Form Submission

When a form is submitted to a linked resource location, the form’s data will be serialized to a JSON object named the Form Submission Object according to the following rules:

  1. Each form field with a value member will be added to the Form Submission Object as a member with the same name having the same value.

  2. If a form field has an object type and a form member, that form field’s value member will first be serialized to a JSON object according to these rules based on the field’s form member. The resulting object will be added to the Form Submission Object as a member having the same name as the field name.

  3. If the form is transmitted to the href linked resource location via a communication protocol that supports content type identification (such as HTTP), the content type MUST be identified as either application/json or application/ion+json.

Consider the following non-normative example form:

Example Form
{
  "href": "https://example.io/users", "rel":["create-form"], "method": "POST",
  "value": [
    { "name": "givenName", "value": "John" },
    { "name": "surname", "value": "Smith" },
    { "name": "username", "value": "jsmith" },
    { "name": "password", "value": "correcthorsebatterystaple", "secret": true },
    { "name": "employer", "label": "Employer", "type": "object", "form": {
        "value": [
          { "name": "name", "label": "Name", "value": "Acme, Inc." },
          { "name": "foundingYear", "label": "Founding Year", "type": "integer", "value": 1900 },
          { "name": "address", "label": "Employer Postal Address", "type": "object", "form": {
              "value": [
                { "name": "street1", "label": "Street 1", "value": "1234 Anywhere Street" },
                { "name": "street2", "label": "Street 2", "value": "Suite 100" },
                { "name": "city", "label": "City", "value": "Anytown" },
                { "name": "state", "label": "State", "value": "NY" }
                { "name": "zip", "label": "Zip", "value": "10001" }
              ]
            }
          }
        ]
      }
    }
  ]
}

The corresponding Form Submission Object for this form might look like this:

Example Form Submission Object
{
  "givenName": "John",
  "surname": "Smith",
  "username": "jsmith",
  "password": "correcthorsebatterystaple",
  "employer": {
    "name": "Acme, Inc.",
    "foundingYear": 1900,
    "address": {
      "street1": "1234 Anywhere Street",
      "street2": "Suite 100",
      "city": "Anytown",
      "state": "NY",
      "zip": "10001"
    }
  }
}

If this form were to be submitted over HTTP, the HTTP request might look as follows:

Example Form Submission HTTP Request
POST /users HTTP/1.1
Host: example.io
Accept: application/ion+json, application/json, */*
User-Agent: Example/1.2.1
Content-Type: application/json

{
  "givenName": "John",
  "surname": "Smith",
  "username": "jsmith",
  "password": "correcthorsebatterystaple",
  "employer": {
    "name": "Acme, Inc.",
    "foundingYear": 1900,
    "address": {
      "street1": "1234 Anywhere Street",
      "street2": "Suite 100",
      "city": "Anytown",
      "state": "NY",
      "zip": "10001"
    }
  }
}

7. Registered Ion Object Member Names

The following member names are registered in the IANA Ion Object Member Registry defined in [TBD]. None of the members defined below are intended to be mandatory in all cases, but rather, provide an initial set likely to be useful for common use cases.

7.1. eform

The eform member value is either a Form object or a Link to a Form object that specifies the required object structure of each element in an Ion Collection Object’s value array. The name "eform" is short for "element form".

If the object is not an Ion Collection Object, or if the object is an Ion Form Field with a type member that does not equal array or set, an Ion parser MUST ignore the object’s eform member.

If the eform member equals null, an Ion parser MUST ignore the eform member.

If the eform member is not a valid Ion Form object, an Ion parser MUST ignore the eform member.

If the eform member exists and is valid, and the etype member does not exist or equals null, an Ion parser MUST assign the object an etype member with a value of object.

If the etype member does not equal object, an Ion parser MUST ignore the eform member.

If the eform member is a Link or a Linked Form, Ion parsers MUST NOT submit data to the eform value’s linked href location. The eform href location may only be used to read the associated form to determine the structure of the associated form object.

If the eform member is contained in an Ion Form Field, and it has been determined that the eform member should be evaluated according to these rules, a validating user agent MUST ensure each element in the field’s value array conforms to the specified eform form structure before form submission.

Use of this member is OPTIONAL.

7.2. etype

The etype member specifies the mandatory data type of each element in an Ion Collection Object’s value array. The name "etype" is short for "element type".

If the object is not an Ion Collection Object, or if the object is an Ion Form Field with a type member that does not equal array or set, an Ion parser MUST ignore the object’s etype member.

If the etype member equals null and the eform member exists and is a valid Ion form, an Ion parser MUST assign the etype member a value of object.

If the etype member does not equal one of the octet sequences defined in Ion Value Object Type Values, an Ion parser MUST ignore the etype member.

If the etype member is contained in an Ion Form Field, and the etype member has been ignored, an Ion parser MUST NOT perform type validation on any value in the object’s value array before form submission.

If the etype member is contained in an Ion Form Field, and it has been determined that the etype member should be evaluated according to these rules, a validating user agent MUST ensure each element in the object’s value array conforms to the specified etype (and any valid associated eform structure) before before form submission.

Use of this member is OPTIONAL.

7.3. form

The form member value is either a Form object or a Link to a Form object that reflects the required object structure of an Ion Value Object’s value member. This allows Ion content authors to define complex data/content graphs.

If the Ion Value Object that contains the form member is a descendent of an Ion Linked Form, Ion parsers MUST NOT submit data to the current form value’s linked href location. The form’s href location may only be used to read the associated form to determine the structure of the associated value object.

Where a Form contains nested Forms in this manner, the resulting collected data will form an object graph. This data/graph may only be submitted to the top-most Ion Linked Form’s href location; Ion parsers MUST NOT submit data to any nested descendant Form’s linked resource location.

7.4. href

The href (hypermedia reference) member identifies the target IRI (Internationalized Resource Identifier) location of the resource. The href value is a case-sensitive IRI value.

If an href member exists, Ion parsers MUST identify the containing JSON Object as an Ion Link in addition to any other Ion Object identified.

Note that in the common case, target IRIs and context IRIs will also be URIs (RFC 3986), because many protocols (such as HTTP) do not support dereferencing IRIs. In serializations that do not support IRIs, IRIs will be converted to URIs according to RFC 3987 Section 3.1.

Use of this member is OPTIONAL.

7.5. method

The method member identifies the HTTP method to be used when sending an HTTP request to the associated href resource location. The method value is a case-sensitive string as defined by RFC 7231 Section 4.1 and safety and idempotent semantics are equivalent to those specified in RFC 7231.

If an href member is defined and a peer method member is not defined, or the method member value is null or not recognized, HTTP GET MUST be used if an HTTP request is made to the linked resource.

Use of this member is OPTIONAL.

7.6. accepts

The accepts member identifies one or more supported representation Media Type that may be submitted to the associated href resource location. The value is a JSON array of strings. Each string in the array MUST be a case-insensitive string as defined by RFC 6838 Section 4.2.

An HTTP user agent may submit an associated representation that conforms to any of these media types. If submitting a representation, that representation’s media type MUST be specified in the HTTP request Content-Type header value as defined by RFC 7321 Section 3.4. Content Negotiation.

Use of this member is OPTIONAL.

7.7. produces

The produces member identifies one or more HTTP response representation Media Types that may be returned from the associated href resource location. The value is a JSON array of strings. Each string in the array MUST be a case-insensitive string as defined by RFC 6838 Section 4.2.

An HTTP server may return a response body that conforms to any of these media types; the exact media type will be specified in the HTTP response Content-Type header as defined by RFC 7321 Section 3.4. Content Negotiation.

Use of this member is OPTIONAL.

7.8. rel

The rel member identifies one or more explicit Link Relation Types assigned to an Ion Link. The value is a JSON array of strings. Each string MUST conform to the relation-type grammar definition in RFC 5988 Section 5.

Use of this member is OPTIONAL.

A Link to a Ion Collection SHOULD contain a rel member that has at least the collection relation specified.

7.9. type

The type member represents the Ion data type that MUST be represented in the associated object’s value member.

Use of this member is OPTIONAL.

7.10. value

The value member indicates that the enclosing object exists to represent a primary JSON value and other members of the object exist to help describe the primary value.

Use of this member is OPTIONAL.

8. Registered Ion Value Object Type Values

The following type member values are registered in the IANA Ion Object Type Registry defined in [TBD]. None of the members defined below are intended to be mandatory in all cases, but rather, provide an initial set likely to be useful for common use cases.

Other type values MAY exist. An Ion parser MUST ignore any type values it does not support.

8.1. array

A non-null value must be a JSON array.

If an Ion Value Object has an array type and the Ion Value Object also contains min, minlength, max, maxlength or pattern members, those members' validation rules apply to each element in the value array, not the array itself.

If an Ion Value Object with an array type also declares an options member, the value array MUST NOT contain any value that does not appear in a nested option value member.

8.2. binary

A non-null value must be a JSON string that is a base64Url-encoded octet sequence according to RFC 4648, Section 5. The string MUST NOT contain characters that are not in the base64Url alphabet.

8.3. boolean

A non-null value must be a JSON boolean.

8.4. date

A non-null value must be a JSON string that conforms to the full-date grammar defined in RFC 3339 Section 5.6.

8.5. datetime

A non-null value must be a JSON string that conforms to the date-time grammar defined in RFC 3339 Section 5.6.

8.6. decimal

A non-null value must be a JSON number that contains a decimal point (aka the Period . character, ASCII code 46).

8.7. duration

A non-null value must be a JSON string that conforms to the duration grammar defined in RFC 3339 Appendix A.

8.8. email

A non-null value must be a JSON string that is also a valid email address as defined in RFC 2822, Section 3.4.

8.9. file

A non-null value must be an Ion File Object.

8.10. integer

A non-null value must be a JSON number that does not contain a decimal point (aka the Period . character, ASCII code 46).

8.11. iri

A non-null value must be a JSON string that is a validly-formed Internationalized Resource Identifier (IRI) as defined by RFC 3987.

A non-null value must be an Ion Link.

8.13. number

A non-null value must be a JSON number.

8.14. object

A non-null value must be a JSON object.

If an Ion Value Object with a type of object also contains a form member, the Ion Value Object’s value member MUST be the Form Submission Object that would result if submitting that form.

8.15. pdatetime

A non-null value must be a partial datetime (a datetime without a timezone) which is a JSON string that conforms to the following ABNF grammar:

pdatetime = full-date "T" partial-time

where full-date and partial-time are defined in RFC 3339 Section 5.6.

To avoid potential logic inconsistencies across heterogeneous systems, it is RECOMMENDED to use datetime instead of pdatetime when possible.

8.16. ptime

A non-null value must be a partial time (a time without a timezone) which is a JSON string that conforms to the partial-time grammar defined in RFC 3339 Section 5.6.

To avoid potential logic inconsistencies across heterogeneous systems, it is RECOMMENDED to use time instead of ptime when possible.

8.17. set

A non-null value must be a JSON array and the array MUST NOT contain any element that is equal to any other element within the same array, where element equality is defined in Appendix A.

If an Ion Value Object has a set type and also contains min, minlength, max, maxlength or pattern members, those members' validation rules apply to each item in the set array, not the set array itself.

If an Ion Value Object with an set type also declares an options member, the value set array MUST NOT contain any value that does not appear in a nested option value member.

8.18. string

A non-null value must be a JSON string.

8.19. time

A non-null value must be a JSON string that conforms to the full-time grammar defined in RFC 3339 Section 5.6.

8.20. url

A non-null value must be a JSON string that is a validly-formed Uniform Resource Locator (URL) as defined by RFC 3986 Section 1.1.3.

9. IANA Considerations

9.1. Ion Object Member Registry

This specification establishes the IANA Ion Object Member Registry for Ion Object Member Names. The registry records the Member Name and a reference to the specification that defines it. This specification registers the Member Names defined in Section 7.

Values are registered on a specification required (RFC 5226) basis after a review period on the Ion Working Group (IWG) ion-doc GitHub repository, on the advice of one or more Designated Experts. However, to allow for the allocation of values prior to publication, the Designated Expert(s) may approve registration once they are satisfied that such a specification will be published.

Registration requests must filed as an ion-doc GitHub issue for review and comment, with an appropriate subject (e.g., "Request to register value object member: example").

Within the review period, the Designated Expert(s) will either approve or deny the registration request, communicating this decision by closing the issue. Denials should include an explanation and, if applicable, suggestions as to how to make the request successful. Registration requests that are undetermined for a period longer than 21 days can be brought to the IWG’s attention using @mentions in a new comment appended to the GitHub issue for resolution.

Criteria that should be applied by the Designated Expert(s) includes determining whether the proposed registration duplicates existing functionality, determining whether it is likely to be of general applicability or whether it is useful only for a single application, and whether the registration description is clear.

IANA must only accept registry updates from the Designated Expert(s) and should direct all requests for registration to the Ion issue tracker.

It is suggested that multiple Designated Experts be appointed who are able to represent the perspectives of different applications using this specification, in order to enable broadly-informed review of registration decisions. In cases where a registration decision could be perceived as creating a conflict of interest for a particular Expert, that Expert should defer to the judgment of the other Expert(s).

Proposed registry description information:

9.1.1. Registration Template

Member Name:

The name requested (e.g., "href"). This name is case-sensitive. Names may not match other registered names in a case-insensitive manner unless the Designated Expert(s) state that there is a compelling reason to allow an exception in this particular case.

Member Description

Brief description of the Member (e.g., "Resource target IRI location").

Change Controller:

For Standards Track RFCs, state "IESG". For others, give the name of the responsible party. Other details (e.g., postal address, email address, home page URI) may also be included.

Specification Document(s):

Reference to the document(s) that specify the parameter, preferably including URI(s) that can be used to retrieve copies of the document(s). An indication of the relevant sections may also be included but is not required.

9.2. Ion Value Object Type Registry

This specification establishes the IANA Ion Value Object Type Registry for Ion Value Object Type Names. The registry records the Type Name and a reference to the specification that defines it. This specification registers the Type Names defined in Section 8.

Values are registered on a specification required (RFC 5226) basis after a review period on the Ion Working Group (IWG) ion-doc GitHub repository, on the advice of one or more Designated Experts. However, to allow for the allocation of values prior to publication, the Designated Expert(s) may approve registration once they are satisfied that such a specification will be published.

Registration requests must filed as an ion-doc GitHub issue for review and comment, with an appropriate subject (e.g., "Request to register value object member: example").

Within the review period, the Designated Expert(s) will either approve or deny the registration request, communicating this decision by closing the issue. Denials should include an explanation and, if applicable, suggestions as to how to make the request successful. Registration requests that are undetermined for a period longer than 21 days can be brought to the IWG’s attention using @mentions in a new comment appended to the GitHub issue for resolution.

Criteria that should be applied by the Designated Expert(s) includes determining whether the proposed registration duplicates existing functionality, determining whether it is likely to be of general applicability or whether it is useful only for a single application, and whether the registration description is clear.

IANA must only accept registry updates from the Designated Expert(s) and should direct all requests for registration to the Ion issue tracker.

It is suggested that multiple Designated Experts be appointed who are able to represent the perspectives of different applications using this specification, in order to enable broadly-informed review of registration decisions. In cases where a registration decision could be perceived as creating a conflict of interest for a particular Expert, that Expert should defer to the judgment of the other Expert(s).

Proposed registry description information:

9.2.1. Registration Template

Member Name:

The type requested (e.g., "integer"). This name is case-sensitive. Names may not match other registered names in a case-insensitive manner unless the Designated Expert(s) state that there is a compelling reason to allow an exception in this particular case.

Member Description

Brief description of the Member (e.g., "JSON number without a decimal point character.").

Change Controller:

For Standards Track RFCs, state "IESG". For others, give the name of the responsible party. Other details (e.g., postal address, email address, home page URI) may also be included.

Specification Document(s):

Reference to the document(s) that specify the parameter, preferably including URI(s) that can be used to retrieve copies of the document(s). An indication of the relevant sections may also be included but is not required.

Appendix A: Appendix

A.1. JSON value equality

Two JSON values are equal if and only if both are:

  • null, or

  • boolean and have the same boolean value, or

  • strings and have the same octet sequence, or

  • numbers and have the same mathematical value, or

  • arrays and have the same number of elements, and elements at the same index are equal according to this definition, or

  • objects and have the same property names, and values for the same property name are equal according to this definition.

A.2. Acknowledgements

The authors acknowledge that the design of the Ion data format was initially influenced by design concepts in RFC 4287, The Atom Syndication Format, specifically the parallels between Atom’s 'Entry' and 'Container' concepts and Ion’s 'Ion Object' and 'Ion Collection' concepts, respectively. The name 'Ion' is a playful nod to the Atom name, honoring this heritage.

Authors' Addresses
Les Hazlewood
Email: [email protected]
URI: http://leshazlewood.com
Company: Okta
Company URI: https://okta.com