/hyper-json

hyper+json media type

Primary LanguageMakefileMIT LicenseMIT

hyper+json

1. Document Status

Author

Cameron Bytheway <cameron@hypergroup.io>, Tim Shadel

Status

Working Draft

Last Updated

2024-09-14

Proposed IANA Registrations

application/hyper+json

2. General

hyper+json is a JSON based hypermedia format designed for simplicity and flexibility.

2.1. Design Goals

hyper+json strives for simplicity:

  • Simple to understand

  • Simple to write

  • Simple to consume

  • Simple to extend

It also tries to be as familiar as possible to JSON users.

2.2. Compliance

An implementation is not compliant if it fails to satisfy one or more of the MUST or REQUIRED elements. An implementation that satisfies all the MUST and REQUIRED elements as well as all the SHOULD and RECOMMENDED elements is said to be "unconditionally compliant"; one that satisfies all the MUST and REQUIRED elements but not all the SHOULD and RECOMMENDED elements is said to be "conditionally compliant."

Note

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

3. Hypermedia Model

3.1. root

The most basic hyper+json resource is an object which MUST contain an href:

{
  "href": "/"
}

3.2. property

hyper+json resources can have arbitrary properties mixed with the hypermedia controls:

{
  "href": "/users/cameron",
  "name": "Cameron",
  "addresses": {
    "home": {
      "street": "123 Fake St.",
      "city": "Nowhere",
      "country": "USA",
      "zip": 12345
    },
    "work": { }
  },
  "likes": [
    "hot-dogs",
    "spoons",
    "toasters"
  ]
}

A hypermedia link is represented as an object with a href property. It MAY have any other properties as desired:

{
  "href": "/users/cameron",
  "name": "Cameron",
  "friends": {
    "href": "/users/cameron/friends",
    "count": 123
  },
  "likes": [
    {"href": "/likes/hot-dogs"},
    {"href": "/likes/spoons"},
    {"href": "/likes/toasters"}
  ]
}

Servers MAY use JSON Pointers prefixed with a #. If href starts with # the pointer references a local property:

{
  "href": "/users/cameron",
  "name": "Cameron",
  "first-name": {
    "href": "#/name"
  },
  "status": {
    "href": "/users/cameron/statuses#/0/text"
  },
  "status-updates": {
    "href": "/users/cameron/statuses#/count"
  }
}

{
  "href": "/users/cameron/statuses",
  "collection": [
    {"text": "I'm happy!"},
    {"text": "Kinda sad... :("}
  ],
  "count": 2
}

3.4. form

A hypermedia form is represented as an object with an action property. It SHOULD have a method property that is specific to the protocol i.e. GET, POST, PUT, DELETE, etc for HTTP.

{
  "href": "/users/cameron",
  "name": "Cameron",
  "update": {
    "action": "/users/cameron",
    "method": "PUT",
    "input": {
      "name": {
        "type": "text",
        "required": true,
        "value": "Cameron"
      }
    }
  }
}

The content-body when submitting the form in this example should be:

{ "name": "Tim" }

Clients SHOULD assume the acceptable type is application/json, unless specified in the enctype:

{
  "href": "/users/cameron",
  "name": "Cameron",
  "update": {
    "action": "/users/cameron",
    "method": "PUT",
    "enctype": "application/x-www-form-urlencoded",
    "input": {
      "name": {
        "type": "text",
        "required": true,
        "value": "Cameron"
      }
    }
  }
}

with the body:

name=Mike

A client SHOULD only submit forms that have understood content-types.

3.5. input

An input control belongs to a form element. It is represented as an object. It contains no required properties. It MAY include the following properties:

type

Specifies the type of the input data. If the type is not set, a client SHOULD default to type text. hyper+json borrows the types specified by the HTML 5 input element specifies, along with the type select. Servers MAY choose to add more types as needed. Clients SHOULD only handle input types they understand.

value

Specifies the current or default value of the input. If value is not set, clients SHOULD default to null.

Servers MAY choose to add more properties as needed. These properties SHOULD be specified in extensions.

3.6. collection

By default, hyper+json resources are single documents. To address a collection of documents servers SHOULD use the collection property. Any included properties in the root document are associated to the collection itself.

{
  "href": "/users",
  "collection": [
    {"href": "/users/cameron"},
    {"href": "/users/tim"},
    {"href": "/users/mike"}
  ],
  "count": 3
}

Servers MAY choose to paginate collection. They SHOULD use the next and prev links to provide pagination:

{
  "href": "/users?page=1",
  "collection": [
    {"href": "/users/cameron"},
    {"href": "/users/tim"},
    {"href": "/users/mike"}
  ],
  "next": {
    "href": "/users?page=2"
  }
}

{
  "href": "/users?page=2",
  "collection": [
    {"href": "/users/ben"},
    {"href": "/users/josh"}
  ],
  "prev": {
    "href": "/users?page=1"
  }
}

3.7. data

Servers MAY use the data property to wrap values and provide extra metadata about an object. Clients SHOULD be aware that any value MAY be wrapped.

Example usages include specifying a profile, specifying a label or deprecating a property.

{
  "href": "/users/1",
  "name": {
    "profile": "https://schema.org/name",
    "label": "Name",
    "data": "Cameron"
  },
  "first-name": {
    "deprecated": true,
    "data": {
      "href": "#/name"
    }
  }
}

3.8. error

{
  "TODO": true
}

4. Examples

{
  "href": "http://example.org/users",
  "collection": [
    {"href": "http://example.org/users/1"},
    {"href": "http://example.org/users/2"},
    {"href": "http://example.org/users/3"}
  ]
}
{
  "href": "http://example.org/users/1",
  "name": "Cameron",
  "favorites": {
    "color": "red",
    "food": ["bananas", "potatoes", "cheese"]
  },
  "update": {
    "action": "http://example.org/users/1",
    "method": "PUT",
    "input": {
      "name": {
        "type": "text",
        "required": true,
        "value": "Cameron"
      },
      "color": {
        "type": "select",
        "options": [
          {"value": "red"},
          {"value": "blue"},
          {"value": "green"}
        ]
      },
      "food": {
        "type": "select",
        "multiple": true,
        "options": [
          {"value": "bananas"},
          {"value": "potatoes"},
          {"value": "cheese"},
          {"value": "carrots"}
        ]
      }
    }
  }
}

5. Extensibility

This document describes the hyper+json markup vocabulary. Any extensions to the standard vocabulary MUST not redefine any objects (or their properties), arrays, properties, link relations, or data types defined in this document. Clients that do not recognize extensions to the standard vocabulary SHOULD ignore them.

The details of designing and implementing extensions is beyond the scope of this document.

Note

It is possible that future forward-compatible modifications to this specification will include new objects, arrays, properties, link-relations, and data types. Extension designers should take care to prevent future modifications from breaking or redefining those extensions.