Version: 0.2.0
Hyperdescribe is a hypermedia message description format used to describe the different components of a hypermedia message. The goal is to provide a standardized way to describe a message in order to:
- Convert to other media types
- Allow the server to respond with multiple media types
- Allow the client to understand multiple media types
The point of this is to create servers and clients that describe and reference hypermedia components rather than work directly with the media types.
The purpose of this format is to make hypermedia easier and to help increase adoption. It is also trying to standardize the way we already think about hypermedia messages. When building a client or server that works with a hypermedia type, there are usually these main components:
- Entities - Anything that has identity (e.g. Person)
- Properites - Properties about that entity (e.g. Name)
- Links - Links to related entities
- Actions - Actions related to this entity
- Embedded Entities - Entities that are embedded withing a parent entity (e.g Person with embedded Address)
- Meta Data - Document- or entity-level data that falls outside of scope of the above
Hyperdescribe provides a way to describe how a particular message conveys these hypermedia components.
{
hyperdescribe: Object
}Now just an object with one root property, hyperdescribe. The hyperdescribe property takes an Entity Object.
An entity is anything that has identity. This can be a person, address, blog post, etc.
{
version: String,
prefixes: Array,
id: String,
classes: Array,
rels: Array,
url: String,
context: Object,
property: String,
content: Object
}versionis a String of the Hyperdescribe version of this entity objectprefixesis a Prefix Object. It is OPTIONAL.idis a String for documen-unique identifier. Eitheridor oneclassesMUST be set, but MAY NOT be both.classesis an Array of Strings of non-unique identifiers. Eitheridor oneclassesMUST be set, but MAY NOT be both.relsis an Array of available link relations for this entity. It is OPTIONAL.urlis a String for theURLof this entity. It SHOULD be consider aselflink relation, along with any other link relations specified in therelsarray. It is OPTIONAL.contextis a Context Object. It is OPTIONAL.propertyis a String for the property name of the parent entity (only used on nested entities). It is OPTIONAL.contentis a Content Object. It is OPTIONAL.
{
name: String,
url: String
}nameis a String of the shortened prefix value (e.g. schema, foaf). It is REQUIRED.urlis a String of the URL that is shortened (e.g. http://schema.org). It is REQUIRED.
By default, Hyperdescribe will honor all of the prefixes in the core initial contexts of RDFa without having to specify them.
{
meta: Object,
properties: Array,
links: Array,
actions: Array,
entities: Array
}metais a Meta Object. It is OPTIONAL.propertiesis an Array of Property Objects. It is OPTIONAL.transitionsis an Array of Transition Objects. It is OPTIONAL.entitiesis an Array of Entity Objects. It is OPTIONAL.
This translates well to HTML+RDFa:
<div id="" class="" rel="" resource="" vobab="" typeof="" prefix="">
<div class="meta"></div>
<div class="properties"></div>
<div class="entities"></div>
<div class="links"></div>
</div>{
data: Object,
code: Array,
links: Array
}datais an Object of name/value pairs. It is OPTIONAL.codeis an Array of Transition Objects, which MUST all be safe, idempotent links. It is OPTIONAL.linksis an Array of Transition Objects, which MUST all be safe, idempotent links. It is OPTIONAL.
{
vocab: String,
typeOf: Array
}Context defines the vocab and typeOf to be used for all of the properties in the Entity Object in which it is found. If a Content Object is used, only typeOf is REQUIRED. This is based on the http://schema.org vocab and how RDFa defines vocabularies and types.
vocabis a String for the URL to the vocab being used for this entity. It is OPTIONAL.typeOfis an Array for the type of entity being described here. It is REQUIRED.
{
type: String,
name: String,
value: String,
label: String,
context: Object
}typeis a String for the type of property here. If not present,textis default- boolean
- date
- dateTime
- time
- float
- int
- text
nameis a String for the name of the property. It is REQUIRED.valueis a String for the value of the property. It is OPTIONAL.labelis a String for an OPTIONAL, human-readable name of the propertycontextis a Context Object. It is OPTIONAL.
{
id: String,
classes: Array,
property: String,
rels: Array,
url: String,
method: String,
isTemplated: Boolean,
responseTypes: Array,
requestTypes: Array,
fields: Array,
bodyTemplate: String,
label: String,
renderAs: String
}idis a String for documen-unique identifier. Eitheridor oneclassesmust be set, but cannot be both.classesis an Array of Strings of non-unique identifiers. Eitheridor oneclassesmust be set, but cannot be both.relsis an Array of available link relations for this link. It is OPTIONAL.urlis a String for theURLof this link. It is REQUIRED.methodis a String for the protocol method to be used when sending a request. By default, it isGET. It is OPTIONAL.isTemplatedis a Boolean stating whether the URL is templated or not. By default, this isfalse. It is OPTIONAL.responseTypesis an Array of media types available to be sent as the response. It is OPTIONAL.requestTypesis an Array of media types the server will accept in the request. It is OPTIONAL.fieldsis an Array of Field Objects. It is OPTIONAL.bodyTemplateis a URI template to be used in the request body. It is OPTIONAL.labelis a String for an OPTIONAL, human-readable name of the property. It is OPTIONAL.renderAsis a String conveying what the link response should be rendered as. It is OPTIONAL.
{
type: String,
name: String,
valueOptions: Array,
defaultValue: String,
value: String,
label: String,
mapsTo: String,
isRequired: Boolean
}typeis a String for the type of the field. This MAY be any value that is allowable in the HTML5<input>tag@typeproperty. It is REQUIRED.nameis a String for the name of the field. It is REQUIRED.optionsis an Array of Option Objects. It is OPTIONAL.defaultValueis a String for the default value of this field. It is conveying the default value of the field, but may be able to change if there is no value specified. It is OPTIONAL.valueis a String for the value of the field. If set, the field MUST be this value and cannot change. It is OPTIONAL.labelis a String for an OPTIONAL, human-readable name of the property. It is OPTIONAL.mapsTois a String that says what this field maps to in either this entity or somewhere else in Hyperdescribe tree. It is OPTIONAL.isRequiredis a Boolean to convey a field is required. By default, it isfalse. It is OPTIONAL.
{
value: String,
label: String
}valueis a String for an option for the value of the field it's within. It is REQUIRED.labelis a String for an OPTIONAL, human-readable name of the property. It is OPTIONAL.
The example below shows an HTML+RDFa representation and the Hyperdescribe document for this message below it.
<!DOCTYPE html>
<html lang="en" prefix="schema: http://schema.org/ s: http://example.com/rels/">
<head>
<title>Top NBA Players of All Time</title>
<link rel="alternate" type="application/hal+json" href="/top-3-players">
</head>
<body>
<h1>Top NBA Players of All Time</h1>
<div class="player" typeof="schema:Player" rel="s:player" resource="/players/jordan/michael">
<h2>
<span property="givenName">Michael</span>
<span property="fullName">Jordan</span>
</h2>
<p><img src="/players/jordan/michael/game-photo.jpg" rel="s:game-photo" alt="Game Photo" /></p>
<p>
Check out Jordan's <a rel="s:stats" href="/players/jordan/michael/stats" title="Stats">stats</a>.
</p>
</div>
<div class="player" typeof="schema:Player" rel="s:player" resource="/players/bird/larry">
<h2>
<span property="givenName">Larry</span>
<span property="fullName">Bird</span>
</h2>
<p>
Check out Bird's <a rel="s:stats" href="/players/bird/larry/stats" title="Stats">stats</a>.
</p>
</div>
<div class="player" typeof="schema:Player" rel="s:player" resource="/players/russell/bill">
<h2>
<span property="givenName">Bill</span>
<span property="fullName">Russell</span>
</h2>
<p>
Check out Russell's <a rel="s:stats" href="/players/russell/bill/stats" title="Stats">stats</a>.
</p>
</div>
<p>
Also check out <a rel="s:nba_worst" href="/nba-worst" title="NBA Worst Players">NBA Worst Players</a>.
</p>
<form name="add-player" method="POST" action="/top-players" rel="s:add_player">
<input type="text" name="givenName" placeholder="First Name" />
<input type="text" name="familyName" placeholder="Last Name" />
</form>
</body>
</html>{
"hyperdescribe": {
"version": "0.1.0",
"entities": [
{
"classes": [ "player" ],
"rels": [ "s:player" ],
"url": "/players/jordan/michael",
"context": {
"typesOf": [ "schema:Player" ]
},
"content": {
"properties": [
{ "name": "givenName", "value": "Michael" },
{ "name": "familyName", "value": "Jordan" }
],
"links": [
{
"rels": [ "s:stats" ],
"url": "/players/jordan/michael/stats",
"label": "Stats"
},
{
"rels": [ "s:game-photo" ],
"url": "/players/jordan/michael/game-photo.jpg",
"label": "Game Photo",
"render": "image"
}
]
}
},
{
"classes": [ "player" ],
"rels": [ "s:player" ],
"url": "/players/bird/larry",
"context": {
"typesOf": [ "schema:Player" ]
},
"content": {
"properties": [
{ "name": "givenName", "value": "Larry" },
{ "name": "familyName", "value": "Bird" }
],
"links": [
{
"rels": [ "s:stats" ],
"url": "/players/bird/larry/stats",
"label": "Stats"
}
]
}
},
{
"classes": [ "player" ],
"rels": [ "s:player" ],
"url": "/players/russell/bill",
"context": {
"typesOf": [ "schema:Player" ]
},
"content": {
"properties": [
{ "name": "givenName", "value": "Bill" },
{ "name": "familyName", "value": "Russell" }
],
"links": [
{
"rels": [ "s:stats" ],
"url": "/players/russell/bill/stats",
"label": "Stats"
}
]
}
}
],
"actions": [
{
"classes": [ "add-player" ],
"label": "Add Player",
"method": "POST",
"url": "/top-players",
"requestTypes": [
"application/x-www-form-urlencoded"
],
"rels": [ "s:add-player" ],
"fields": [
{
"name": "givenName",
"type": "text",
"label": "First Name"
},
{
"name": "familyName",
"type": "text",
"label": "Last Name"
}
]
}
]
}
}