A handler to explore and display all the contents available in an OpenCms installation. The folder handler allows to navigate the complete multi-site and multi-lingual tree of a website in any depth. On each level of the tree it informs about properties and attributes attached to a resource.
The JSON API is a headless REST API for the delivery of CMS contents in the JSON format. It is suitable for modern frontend technologies such as single-page applications or progressive web applications.
Features
- Content Handler
A handler to create detail views for individual contents. The content handler provides utility features for locale handling and linked contents.
- List Handler
Editors with OpenCms can create preconfigured content lists that collect items of a content type - or even mixed content types - taking into account various list options such as category filtering and sorting. The list handler allows to display such preconfigured lists with the possibility to dynamically change the configured list options by means of request parameters.
- The OpenCms JSON API is read-only for presentation purposes, content edition is not possible.
- Only publicly available online contents without access restrictions are accessible.
- There is no authentication mechanism yet to access offline contents or online contents with access restrictions.
- The list handler is incomplete, e.g. it does not provide faceted browsing.
In order to experiment with the JSON REST API, there is a preconfigured OpenCms docker image with some React demo applications available.
Unlike with the demo docker image, the JSON API is not activated by default in a standard OpenCms distribution. This is because the JSON API makes all resources and resource properties of all sites publicly available.
Before activating the JSON API on a production server, you should consider the access policy.
In order to activate the JSON API, add the org.opencms.xml.xml2json.CmsJsonResourceHandler
resource handler class at the end of the handler list in the opencms-system.xml configuration file.
<resourceinit>
<resourceinithandler class="org.opencms.pdftools.CmsPdfResourceHandler" />
<resourceinithandler class="org.opencms.jsp.userdata.CmsUserDataResourceHandler" />
<resourceinithandler class="org.opencms.xml.xml2json.CmsJsonResourceHandler" />
</resourceinit>
If no access policy configuration file is given for the JSON resource handler, all resources and resource properties are publicly available. In order to restrict access, add a paramater access-policy with a path to an access policy file (path is in the virtual file system) to the resource handler.
<resourceinit>
<resourceinithandler class="org.opencms.xml.xml2json.CmsJsonResourceHandler">
<param name="access-policy">/shared/json-access.xml</param>
</resourceinithandler>
</resourceinit>
The access policy configuration file has the following structure:
<json-access>
<include>/path1.*</include>
<include>/path2.*</include>
<exclude>/path1.*</exclude>
<exclude>/path2.*</exclude>
<property-filter>(?i)^(?!.*(?:secret|api|password|key)).*$</property-filter>
<cors>
<allow-origin>*</allow-origin>
<allow-methods>*</allow-methods>
<allow-headers>*</allow-headers>
</cors>
</json-access>
Parameter | Description | Default |
---|---|---|
include | Access is granted only for resources matching the given regular expression. | Access is granted for all resources if include is not present. |
exclude | Access is denied for resources matching the given regular expression. | Access is granted for all resources if exclude is not present. |
property-filter | Property access is denied for properties matching the given regular expression. | Access is granted for all properties except for property names containing "secret", "api", "password", and "key" if property-filter is not present |
cors/allow-origin | For each JSON response, the HTTP response header Access-Control-Allow-Origin with the given value is set. | The HTTP response header is * if allow-origin is not present. |
cors/allow-methods | For each JSON response, the HTTP response header Access-Control-Allow-Methods with the given value is set. | The HTTP response header is * if allow-methods is not present. |
cors/allow-headers | For each JSON response, the HTTP response header Access-Control-Allow-Headers with the given value is set. | The HTTP response header is * if allow-headers is not present. |
- Resource. The resource type is the top level type of the JSON API. A resource can either be a file or a folder. For every resource requested, the JSON API responds with a resource wrapper containing metadata. See the section Resource Handler below for details about the JSON format.
- Folder. Folder is a container for any of the types below (file, content, list, page, other).
- File. File is either a content file or a file of some other type.
- Content. The content type is the most relevant for the JSON API since it provides the actual website content. Whenever a content file is requested, a multi-lingual JSON wrapper with a defined inner content type is returned as described in section Content Handler below.
- List. The list type is a special content type with no multi-lingual wrapper. It is a content configuration file that collects contents of any type according to user-defined filter and sort criteria.
- Page. The page type is also a special content type with no multilingual wrapper. It provides display information to be used when rendering contents on a page. See the section Page Handler below.
- Other. Files other than content files (images, audios, text files, binary files, etc.) can be streamed outside the JSON API. The JSON API in this case returns a resource wrapper only with metadata.
- Content. The content type is the most relevant for the JSON API since it provides the actual website content. Whenever a content file is requested, a multi-lingual JSON wrapper with a defined inner content type is returned as described in section Content Handler below.
Each resource in OpenCms is available via a unique file system URI. The most relevant URIs are the following:
The JSON Endpoint URI
GET /json/?wrapper=false
{
"shared": {},
"sites": {},
"system": {}
}
All JSON contents are available below the json endpoint. The JSON endpoint always returns the same three folders named sites, shared, and system.
- sites contains all sites and sub-sites available in an OpenCms installation
- shared is a folder for contents that can be shared by the sites
- system contains a lot of OpenCms internal files, where only the content Schema files are relevant for the JSON API
Site and Sub-Site URIs
GET /json/sites/?wrapper=false&levels=3
{
"alkacon": {
"children": {
".content": {},
"web": {
"children": {
".content": {},
"index.html": {}
}
},
"intranet": {
"children": {
".content": {},
"index.html": {}
}
},
"opencms": {
"children": {
".content": {},
"index.html": {}
}
}
}
}
}
The sites folder contains an arbitrary number of websites. Each site can have an arbitrary number of sub-sites. You can recognize site and sub-site folders by their child .content folder where all the contents of a (sub-)site live. Folders without a .content folder are usually no (sub-)sites but page levels.
The example shows a site called alkacon. The alkacon site has three sub-sites called web, intranet, and opencms, identifiable by their .content folder.
Page URIs
GET /json/sites/{site}[/{sub-site}]/**/index.html
An index.html file inside a site or sub-site folder usually represents a page. Requesting an index.html file returns a page in a JSON format as described in the sections Page Handler below.
Sometimes, an index.html can be a redirect or a script. The JSON API resource wrapper informs about such special cases.
Content URIs
GET /json/sites/{site}[/{sub-site}]/.content/
{
".config": {},
"article-m": {},
"contact-m": {},
"decoy-m": {},
"event-m": {},
"list-m": {},
...
}
You can find contents below the .content folders of sites and sub-sites.
Listing a .content folder gives an overview of the content types available for a site.
The example response shows some content types of OpenCms' standard template Mercury.
Content schema URIs
GET /json/system/modules/alkacon.mercury.template/schemas/?wrapper=false
{
"article.xsd": {},
"contact.xsd": {},
"decoy.xsd": {},
"event.xsd": {},
"faq.xsd": {},
"flexible.xsd": {},
...
}
OpenCms uses an easy to understand sub-set of the XML schema language to describe the models of content types.
The example response shows the Schema files of OpenCms' default template Mercury.
The JSON API currently supports the following request parameters:
- content (boolean)
- fallbackLocale (boolean)
- levels (integer)
- locale (string)
- path (string)
- rows (integer)
- sort (enumeration)
- start (integer)
- wrapper (boolean)
Parameters have either boolean, integer, enumeration, or string values.
The wrapper, content, locale, and fallbackLocale parameters are available for the content type, the list type, the page type, as well as for the folder type.
- Name
Description
- content
With the content parameter, additional contents can be embedded in a JSON response document. Depending on the actual handler, the content embedded can have different origins. For the Folder Handler, content is embedded for all children files of a folder in line with the already present resource wrappers. For the List Handler, the content parameter causes the JSON API to evaluate the list configuration and appends the resulting list contents at the end of the JSON document. For the Content Handler and the Page Handler, the content parameter searches for all contents that are linked to the requested content or the requested page and embeds the linked contents. The content parameter in the end means "show me as much content as possible". It is an utility parameter shifting the complexity of the various content relations (content as list result, linked contents, file contents, etc.) from the client to the API.
- wrapper
Shows and hides the resource wrappers in a JSON document of the JSON response. This is especially useful to optimize the size of large JSON documents that contain a large number of content and resource files. The resource wrapper and the content are two independent parts of a JSON response document that can be turned on and off independently of each other depending on the actual requirements.
- locale
A frontend usually is not interested in all the locales a content is available for but in the locale currently selected by the client. Thus, it is common practice to always select a single locale with the locale parameter. Just like the wrapper parameter, the locale parameter can significantly reduce the size of the response document.
- fallbackLocale
It is common practice to always use the locale parameter in combination with the fallbackLocale parameter to avoid empty results, i.e., to always have some default locale content available in the response document
The other parameters are handler specific:
The Folder Handler has an additional levels parameter to define the depth of folder recursion
The List Request supports the start, rows, and sort parameters for result sorting and result paging.
Boolean parameters evaluate to true if the parameter value is either "true", or empty, or not present:
- ?{paramName}=true
- ?{paramName}=
- ?{paramName}
Boolean parameters evaluate to false only if the parameter value is set to false
- ?{paramName}=false
If a boolean parameter is not present at all, an internal default value is assumed as described below.
Request URI scheme
/json/{dir}/{resource}
Property | Description | JSON Type |
---|---|---|
attributes | Technical metadata about the requested resource. | Object |
attributes.lastModified | Timestamp when the requested resource was last modified. | Number |
attributes.type | The internal type of the requested resource. | String |
isFolder | Whether the requested resource is a folder. | Boolean |
isXmlContent | Whether the requested resource is a content. | Boolean |
link | The absolute path of the requested resource relative to the site root. | String |
own_properties | The properties directly attached to the requested resource. | Object |
requestParams | Just repeats the request parameters and informs which default value is used for each parameter. | Object |
path | The full absolute path of the requested resource including the path of the site. | String |
properties | The properties of the resource itself plus the properties inherited from the parent and descendant folders. | Object |
JSON format
{
"attributes": {
"lastModified": 1628004683200,
"type": "binary"
},
"isFolder": false,
"isXmlContent": false,
"link": "/mercury-demo/.galleries/Downloads/OpenCms-is-just-fun.pdf",
"own_properties": {
"Title": "OpenCms is just fun"
},
"path": "/sites/default/mercury-demo/.galleries/Downloads/OpenCms-is-just-fun.pdf",
"properties": {
"Title": "OpenCms is just fun",
"Description": "An advanced OpenCms Mercury template demo site, brought to you by Alkacon Software.",
"NavPos": "0.12",
"NavStartLevel": "1",
"NavText": "Mercury Demo EN",
"NavText_de": "EN"
},
"requestParams": {}
}
Applies if the requested JSON URL targets to a content, i.e., it targets not to a page or list.
Request URI scheme
/json/{dir}/{content}?locale={locale}&fallbackLocale={boolean}&path={path}&wrapper={boolean}
Parameters | Default Value | Description | Dependency |
---|---|---|---|
[none] | Returns a JSON representation of an XML content along with a wrapper containing metadata. | ||
?locale={locale} | [not set] | If set, returns the localized part of the XML content only without the wrapper. | |
?fallbackLocale={boolean} | false | If set to true, falls back to another locale if the locale selected by {locale} does not exist. | locale |
?path={path} | [not set] | If set, returns a fragment of a localized part of an XML content. | locale |
?wrapper={boolean} | false if locale or path is set, true otherwise | If set, overwrites the default value. |
Property | Description |
---|---|
[Resource Wrapper] | Since the content type is a sub-type of the resource wrapper type, it inherits all properties of the resource wrapper as explained above. |
en, de, [locale] | Locale names. As a default, OpenCms has locales en and de configured. If there are more locales configured, the names of the configured locales appear as first level properties in line with en and de, see [locale]. |
[Locale Content] | Can be any content of any content type available in a template. For the Mercury template, this is type article-m, contact-m, event-m, and so on. Locale contents may link other contents, see [full path to the linked content]. |
localeContent | Is a wrapper element where the [Locale Content] appears if a specific locale is requested with parameter locale. |
locales | The list of locales the requested resource is available for. |
linkedContents | Contents may link other contents. If such linked contents exist for a requested resource, they appear as a map in the linkedContents property with the [full path to the linked content] as the key of the map and the linked content itself as the value of the map. |
JSON format
{
[Resource Wrapper]
"en": {
[Locale Content]
"Link": {
"path": "[full path to a linked content]"
}
},
"de": {
[Locale Content]
},
"[locale]": {
[Locale Content]
}
"localeContent": {
[Locale Content]
},
"locales": [
"en",
"de",
"[locale]"
],
"linkedContents": {
"[full path to a linked content]": [Content]
}
}
Request URI scheme
/json/{folder}/?levels={number}&content={boolean}&locale={locale}&fallbackLocale={boolean}&wrapper={boolean}
Parameters | Default Value | Description | Dependency |
---|---|---|---|
[none] | Returns a directory listing with all child directories and child files contained in {folder}. | ||
?levels={number} | 1 | For a given number of levels, returns a nested directory tree with all child directories and child files contained in {folder}. | |
?content={boolean} | false | If set to true, embeds all XML contents inside the folder listing or the folder tree. | |
?locale={locale} | [not set] | If set, embeds all XML contents but only the localized parts of the contents selected by {locale}. | content |
?fallbackLocale={boolean} | false | If set to true, falls back to another locale if the selected locale does not exist. | locale |
?wrapper={boolean} | false if locale or path is set, true otherwise | If set, overwrites the default value. |
Property | Description | JSON Type |
---|---|---|
[folder name], [file name] | For a requested folder resource, all child folders and child files are returned in the form of a map with the [folder name] or [file name] as the key of the map and at least with the [Resource Wrapper] as the value of the map. With the content parameter, also the [Content] can be embedded in the folder response for child files of type content. |
Object |
children | If a child resource of the requested folder is a folder itself there may be a children property that recursively embeds the children of a child folder of the requested resource. The children property appears if a value greater than 1 is choosen for the levels request parameter. |
JSON format
{
"[folder name]": {
[Resource Wrapper]
"children": {
"[folder name]": {
[Resource Wrapper]
},
"[file name]": {
[Resource Wrapper]
[Content]
}
}
},
"[file name]": {
[Resource Wrapper]
[Content]
}
}
Request URI scheme
/json/{dir}/{listconfig}?content={boolean}&locale={locale}&fallbackLocale={boolean}&start={number}&rows={number}&sort={sort}
Parameters | Default Value | Description | Dependency |
---|---|---|---|
[none] | Returns the list configuration. | ||
?content | false | Evaluates the list configuration and appends the content list to the result along with list information. | |
?locale={locale} | [not set] | If set, returns the localized part of the XML contents only without the wrapper. | content |
?fallbackLocale={boolean} | false | If set to true, falls back to another locale if the locale selected by {locale} does not exist. | locale |
?wrapper={boolean} | false if locale is set, true otherwise | If set, overwrites the default value. | content |
?start={start} | 0 | If set, returns a part of the list only, i.e., the list items starting at index {start}. | content |
?rows={rows} | 600 | If set, returns a part of the list only, i.e., the a maximum of {rows} list items. | content |
?sort={sort} | [configured sort order] | If set, overwrites the configured sort order; possible values are DATE_ASC, DATE_DESC, TITLE_ASC, TITLE_DESC, ORDER_ASC, ORDER_DESC. |
The list response contains the list configuration and the list result. The list results appear when the content parameter is set to true.
Property | Description | JSON Type |
---|---|---|
List Configuration | ||
Category, CategoryFolderFilter, CategoryMode | Categories configured to restrict the list result. | String |
SearchFolder | Folders configured to search contents in. | Array |
ShowExpired | Whether to list expired contents. | Boolean |
SortOrder | The configured default list sort order. One of DATE_ASC, DATE_DESC, TITLE_ASC, TITLE_DESC, ORDER_ASC, ORDER_DESC. Can be overwritten with the sort parameter. | String |
Title | The internal name of the list. | String |
TypesToCollect | Content types configured that shall be collected. | Array |
List Result | ||
linkedContents | Contents that are linked by one of the contents in the result list. | Object |
listInfo | Information about the list result. | Object |
listInfo.numFound | Total number of list items found. | Number |
list | The contents found. |
JSON format
{
"Category": "",
"CategoryFolderFilter": [],
"CategoryMode": "OR",
"SearchFolder": [
{
"link": "https://my-def-demo.alkacon.com/mercury-demo/.content/article-m/",
"path": "/sites/default/mercury-demo/.content/article-m/"
}
],
"ShowExpired": true,
"SortOrder": "DATE_DESC",
"Title": "Basic Blog List (with elaborate teasers)",
"TypesToCollect": [
"m-article:m/display/article-elaborate"
],
"linkedContents": {},
"list": [
{
[Resource Wrapper]
[Content]
},
{
[Resource Wrapper]
[Content]
}
],
"listInfo": {
"numFound": 76
}
}
Request URI scheme
/json/{dir}/{page}?content={boolean}&wrapper={boolean}&locale={locale}&fallbackLocale={boolean}
Parameters | Default Value | Description | Dependency |
---|---|---|---|
[none] | Returns a JSON representation of the of the page informing about the referenced contents and their structure. | ||
?content={boolean} | false | If set to true, expands all referenced contents and appends them at the end of the JSON document. | |
?locale={locale} | [not set] | If set, appends all contents at the end of the JSON document, but only the localized parts of the contents selected by {locale}. | content |
?fallbackLocale={boolean} | false | If set to true, falls back to another locale for the embedded contents if the selected locale does not exist for an embedded content. | locale |
?wrapper={boolean} | false if locale or path is set, true otherwise | If set, shows the expanded contents with wrapper. |
The page type is a tree with two nested types Container and Element.
Page is the root node of the tree model. It may contain one or more Containers.
Container is a wrapper for a collection of arbitrary elements in a defined order.
Element contains a content with additional formatting settings informing about how to display the content in this specific context.
Property | Description | JSON Type |
---|---|---|
Page | ||
containers | The list of containers the requested page contains. | List |
linkedContents | linkedContents is the property where all the contents or model groups the requested page links to in its elements are embedded. | List |
Container | ||
elements | The list of elements this container contains. | List |
isNestedContainer | Whether this container is a nested container. | Boolean |
isRootContainer | Whether this container is a root level container. | Boolean |
name | The name of this container. | String |
type | A comma-separated list of type names that are allowed as children in this container. | String |
Element | ||
formatterKey | Formatter key of this element indicating how the content of this element should be displayed. | String |
path | The full path of the content this element links to. The path link is resolved in the linkedContents property of the page. |
String |
settings | Additional styling information for content formatting such as CSS classes, margins or colors. | Object |
JSON format
{
[Resource Wrapper]
"containers": [
{
"elements": [
{
"containers": [],
"formatterKey": "m/layout/group",
"path": "/sites/default/.content/modelgroup/modelgroup-00001.html",
"settings": {
"addBottomMargin": "true",
"fixedheader": "fixed",
"showBreadcrumbs": "true"
}
},
{
"containers": [
[more containers and elements]
],
"formatterKey": "m/layout/area-simple",
"path": "/system/shared/mercury/template/layout-area/la_00001.xml",
"settings": {
"bgColor": "none",
"bgSpacing": "none"
}
},
],
"isDetailOnlyContainer": false,
"isNestedContainer": false,
"isRootContainer": true,
"name": "mercury-page",
"type": "area"
}
],
"linkedContents": {
"/system/shared/mercury/template/layout-area/la_00001.xml": {
[Content]
},
"/sites/default/.content/modelgroup/modelgroup-00001.html": {
[Modelgroup]
}
}
}