An intuitive JSON-based hypermedia type for REST.
This document specifies the Ion Hypermedia Type, a simple and intuitive JSON-based hypermedia type for REST.
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 August 2018.
Copyright (c) 2013-2018 Ion Working Group and persons identified as document authors. All rights reserved.
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.
These terms are defined by this specification:
A JSON name/value pair as defined in RFC 7159.
The single JSON object at the root of an Ion content structure.
A JSON object with a member named value
.
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.
The referent of an International Resource Identifier.
A Resource that is also a Collection Object.
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.
A JSON object with members that describe a named value that may be collected and submitted to a linked resource location.
A Value Object with a value
that may be applied to the containing Form Field’s value
.
An Collection Object where the value
array member contains Form Fields.
A Form that is also a Link. Form data submitted will be sent to the form’s href
resource location.
A Value Object where the value
member is a Base64URL-encoded byte array that also has mimetype
and name
members
representing file metadata.
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
All following examples are non-normative.
JSON objects are parsed as expected:
{
"firstName": "Bob",
"lastName": "Smith",
"birthDate": "1980-01-23"
}
A Value Object is a JSON object with a value
member:
{
"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:
{
"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:
{
"name": "Joe",
"employer": { "href": "https://example.io/corporations/acme" }
}
A Collection Object is a Value Object where the value
member is a JSON array:
{
"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:
{
"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:
{
"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:
{
"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"
}
]
}
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).
{
"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" }
]
}
}
]
}
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.
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.
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:
-
MUST recognize all members defined in the Ion Object Member Registry,
-
MAY recognize members which are not defined in the Ion Object Member Registry,
-
MUST ignore members which it does not understand.
Consider the following non-normative example of an object with a greeting
member:
{
"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:
{
"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.
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.
Ion parsers MUST identify any JSON object as an Ion File Object if the object contains:
-
a non-null
name
string member. -
a non-null
mediatype
string member that equals a syntactically valid Media Type string value. -
a non-null
value
string member that is abase64Url
-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 thebase64Url
alphabet. -
either a
type
member equal to the octet sequencefile
or the object is in a Collection Object’svalue
array and the Collection Object has anetype
member with a value equal to the octet sequencefile
.
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.
An Ion File Object contains one or more of the following members.
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.
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.
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.
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:
{ "href": "https://example.io/corporations/acme" }
A non-normative example of an 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:
-
Root Object
-
Named Link
-
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:
{ "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.
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.
Ion parsers MUST identify any JSON object as an Ion Form if the object matches the following conditions:
-
Either:
-
The JSON object is discovered to be an Ion Link as defined in Section 4 AND its
meta
member has an internalrel
member that contains one of the octet sequencesform
,edit-form
,create-form
orquery-form
, OR: -
The JSON object is a member named
form
inside an Ion Form Field.
-
-
The JSON object has a
value
array member with a value that is notnull
or empty. -
The JSON object’s
value
array contains one or more Ion Form Field objects. -
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 }
]
}
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.
An Ion Form Field contains one or more of the following members.
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.
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.
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.
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.
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.
The label
member is a human-readable string that may be used to enhance usability.
Use of this member is OPTIONAL.
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.
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.
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.
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.
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.
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.
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.
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.
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
.
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.
The placeholder
member is a short hint string that describes the expected field value
.
Use of this member is OPTIONAL.
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.
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.
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.
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.
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.
An Form Field Option has one or more of the following members.
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.
The label
member is a human-readable string that may be used to enhance usability.
Use of this member is OPTIONAL.
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:
-
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. -
If a form field has an
object
type and aform
member, that form field’svalue
member will first be serialized to a JSON object according to these rules based on the field’sform
member. The resulting object will be added to the Form Submission Object as a member having the same name as the field name. -
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 eitherapplication/json
orapplication/ion+json
.
Consider the following non-normative 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:
{
"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:
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"
}
}
}
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
A non-null value must be a JSON string that conforms to the full-date
grammar defined in RFC 3339 Section 5.6.
A non-null value must be a JSON string that conforms to the date-time
grammar defined in RFC 3339 Section 5.6.
A non-null value must be a JSON number that contains a decimal point (aka the Period .
character, ASCII code 46).
A non-null value must be a JSON string that conforms to the duration
grammar defined in RFC 3339 Appendix A.
A non-null value must be a JSON string that is also a valid email address as defined in RFC 2822, Section 3.4.
A non-null value must be an Ion File Object.
A non-null value must be a JSON number that does not contain a decimal point (aka the Period .
character, ASCII code 46).
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 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.
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.
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.
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.
A non-null value must be a JSON string that conforms to the full-time
grammar defined in
RFC 3339 Section 5.6.
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.
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:
-
Protocol Category: Ion
-
Registry Location: http://www.iana.org/assignments/ion
-
Webpage Title: Ion
-
Registry Name: Ion Object Members
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.
Brief description of the Member (e.g., "Resource target IRI location").
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.
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.
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:
-
Protocol Category: Ion
-
Registry Location: http://www.iana.org/assignments/ion
-
Webpage Title: Ion
-
Registry Name: Ion Value Object Types
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.
Brief description of the Member (e.g., "JSON number without a decimal point character.").
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.
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.
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.
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.
Les Hazlewood Email: les@hazlewood.com URI: http://leshazlewood.com Company: Okta Company URI: https://okta.com