Most representations returned from the API are Shoji Documents. Shoji is a media type designed to foster scalable APIs. Shoji is built with JSON, so any JSON parser should be able to at least deserialize Shoji documents. Shoji adds four document types: Entity, Catalog, View, and Order.
Entity
Anything that can be thought of as “a thing by itself” will probably be represented by a Shoji Entity Document. Entities possess a “body” member: a JSON object where each key/value pair is an attribute name and value. For example:
{
"element": "shoji:entity",
"self": "https://.../api/users/1/",
"description": "Details for a User.",
"specification": "https://.../api/specifications/users/",
"fragments": {
"address": "address/"
},
"body": {
"first_name": "Genghis",
"last_name": "Khan"
}
}
In general, an HTTP GET to the “self” URL will return the document, and a PUT of the same will update it. PUT should not be used for partial updates–use PATCH for that instead. In general, each member included in the “body” of a PATCH message will replace the current representation; attributes not included will not be altered. There is no facility to remove an attribute from an Entity.body via PATCH. In some cases, however, even finer-grained control is possible via PATCH; see the Endpoint Reference for details.
Catalog
Catalogs collect or contain entities. They act as an index to a collection, and indeed possess an “index” member for this:
{
"element": "shoji:catalog",
"self": "https://.../api/users/",
"description": "A list of all the users.",
"specification": "https://.../api/specifications/users/",
"orders": {
"default": "default_order/"
},
"index": {
"2/": {"active": true},
"1/": {"active": false},
"4/": {"active": true},
"3/": {"active": true}
}
}
Each key in the index is a URL (possibly relative to “self”) which refers to a different resource. Often, these are Shoji Entity documents, but not always. The index also allows some attributes to be published as a set, rather than in each individual Entity. This allows clients to act on the collection as a whole, such as when rendering a list of references from which the user might select one entity.
In general, an HTTP GET to the “self” URL will return the document, and a PUT of the same will update it. Many catalogs allow POST to add a new entity to the collection. PUT should not be used for partial updates–use PATCH for that instead. In general, each member included in the “index” of a PATCH message will replace the current representation; tuples not included will not be altered. Tuples included in a PATCH which are not present in the server’s current representation of the index may be added; it is up to each resource whether to support (and document!) this approach or prefer POST to add entities to the collection. In general, catalogs that contain entities get new entities created by POST, while catalogs that collect entities that are contained by other catalogs (e.g. a catalog of users who have permissions on a dataset) will have entities added by PATCH.
Similarly, removing entities from catalogs is supported in one of two ways, typically varying by catalog type. For catalogs that contain entities, entities are removed only by DELETE on the entity’s URL (its key in the Catalog.index). In contrast, for catalogs that collect entities, entities are removed by PATCHing the catalog with a null tuple. This removes the entity from the catalog but does not delete the entity (which is contained by a different catalog).
View
Views cut across entities. They can publish nearly any arrangement of data, and are especially good for exposing arrays of arrays and the like. In general, a Shoji View is read-only, and only a GET will be successful.
Order
Orders can arrange any set of strings into an arbitrarily-nested tree; most often, they are used to provide one or more orderings of a Catalog’s index. For example, each user may have their own ordering for an index of variables; the same URL’s from the index keys are arranged in the Order. Given the Catalog above, for example, we might produce an Order like:
{
"element": "shoji:order",
"self": "https://.../api/users/order/",
"graph": [
"2/",
{"group A": ["1/", "3/", "2/"]},
{"group B": ["4/"]}
]
}
This represents the tree:
/ | \
2 {A} {B}
/ | \ \
1 3 2 4
The Order object itself allows lots of flexibility. Each of the following decisions are up to the API endpoint to constrain or not as it sees fit (see the Endpoint Reference for these details):
- Not every string in the original set has to be present, allowing partial orders.
- Strings from the original set which are not mentioned may be ignored, or default to an “ungrouped” group, or other behaviors as each application sees fit.
- Groups may contain member strings and other groups interleaved (but still ordered).
- Groups may exist without any members.
- Members may appear in more than one group.
- Group names may be repeated at different points within the tree.
- Group member arrays, although represented in a JSON array, may be declared to be non-strict in their order (that is, the array should be treated more like an unordered set).