HAL-FORMS Extensions

The HAL-FORMS specification defines request body encodings for application/json and application/x-www-form-urlencoded.

ContentGrid extends the HAL-FORMS specification:

  • to allow construction of nested JSON objects for application/json request body encoding
  • to define request body encodings for multipart/form-data and text/uri-list
  • the options element is extended to define the behavior of a link with a mediatype of application/hal+json and application/prs.hal-forms+json

Body encoding for application/json

To encode a nested JSON object, the property name will be interpreted as a property path.

Properties for which no value is present are not taken into account for serialization purposes.

Nested JSON encoding

Given this HAL-FORMS template:

{
  "contentType": "application/json",
  "properties": [
    {
      "name": "received",
      "prompt": "Received",
      "required": true,
      "type": "datetime"
    },
    {
      "name": "document.mimetype",
      "prompt": "Document mimetype",
      "type": "text"
    },
    {
      "name": "document.filename",
      "prompt": "Document filename",
      "type": "text"
    },
    {
      "name": "pay_before",
      "prompt": "Pay before",
      "required": true,
      "type": "datetime"
    },
    {
      "name": "total_amount",
      "prompt": "Total amount",
      "required": true,
      "type": "number"
    }
  ]
}

The request body is serialized as:

{
  "received": "2024-05-08T14:58:23Z",
  "document": {
      "mimetype": "text/plain",
      "filename": "example.txt"
  },
  "pay_before": "2024-06-08T00:00:00Z",
  "total_amount": 14.58
}

Body encoding for multipart/form-data

When sending bodies encoded as multipart/form-data, bodies SHOULD be encoded according to the WhatWG HTML standard.

Body encoded for text/uri-list

When sending bodies encoded as text/uri-list, the HAL-FORMS template MUST only contain a single property of type url.

Only the value (or values if the property is multi-value) of the property is part of the request body, in accordance to the text/uri-list mime type.

Multi-valued properties are serialized by having each value on a separate line.

uri-list encoding

Given this HAL-FORMS template:

{
  "contentType": "text/uri-list",
  "properties": [
    {
      "name": "supplier",
      "type": "url"
    }
  ]
}

The request body is serialized as:

http://example.com/example-path?q=abc

Extension for options element

The options element contains an enumerated list of possible values for a property.

When the options element contains a link attribute, the possible values are to be retrieved from a remote HTTP resource.

The link attribute has following child-attributes, with the same meaning as the HAL Link Object:

  • href
  • type
  • templated
  • profile

The behavior of the options element promptField and valueField attributes are dependent on the content-type of the remote HTTP resource. The type attribute may be used as a hint for the content-type of the remote HTTP resource, but the actual content-type of the response is authoritative.

Content-Type of remote resource list of values taken from Interpretation of promptField / valueField
application/json items in the top-level array element name of the JSON field to use for prompt/value of the element (default prompt/value)
text/csv rows in the CSV document 0-indexed column number of the row to use for prompt/value of the element (default 0/1)
application/hal+json or application/prs.hal-forms+json embedded resources (_embedded) with link relation type item. Pagination using prev/next links may be used. JSON pointer to the JSON value to use for prompt/value of the element (default empty pointer//_links/self/href)
Example

Given a HAL-FORMS property:

{
  "name": "supplier",
  "options": {
    "link": {
      "href": "https://app.contentgrid.example/suppliers"
    }
  }
}

The following responses by the remote HTTP resources are possible, which all result in a very similar way of displaying.

Content-Type Simple Array Key/Value Array

application/json

["Fedex","UPS","DHL"]
[
  {"prompt" : "Federal Express", "value" : "FedEx"},
  {"prompt" : "United Parcel Service", "value" : "UPS"},
  {"prompt" : "DHL Express", "value" : "DHL"}
]

text/csv

Fedex
UPS
DHL
Federal Express,FedEx
United Parcel Service,UPS
DHL Express,DHL

application/hal+json or application/prs.hal-forms+json

N/A

{
  "_embedded": {
    "item": [
      {
        "name": "Federal Express",
        "_links": {
          "self": {
            "href": "https://app.contentgrid.example/suppliers/FedEx"
          }
        }
      },
      {
        "name": "United Parcel Service",
        "_links": {
          "self": {
            "href": "https://app.contentgrid.example/suppliers/UPS"
          }
        }
      }
    ]
  },
  "_links": {
    "next": {
      "href":  "https:/app.contentgrid.example/suppliers?page=2"
    }
  }
}

with on the next page:

{
  "_embedded": {
    "item": [
      {
        "name": "DHL Express",
        "_links": {
          "self": {
            "href": "https://app.contentgrid.example/suppliers/DHL"
          }
        }
      }
    ]
  },
  "_links": {
    "prev": {
      "href":  "https:/app.contentgrid.example/suppliers?page=1"
    }
  }
}
Note

For the HAL-based resource, the resolved prompt value would be the full item object. It is up to the implementation how to display this object. If this is unwanted, promptField can be set to a JSON pointer to select a specific field as a prompt. (e.g. "promptField": "/name")

Property path

A property path is used to reference fields in nested JSON objects.

The property path is built by separating JSON fields with .. e.g. document.filename will be serialized as a top-level field document which is assigned to an object with a filename field.