Skip to main content

REST Components

Components providing a REST API are marked using the Component-level option enableJaxrs. An application can contain more than one Component which exposes a REST API, but each Component will represent a separate API.

Option
enableJaxrs Component

This option enables the expansion of the REST API code using JAX-RS in the Component. This is required to generate all files required to create a REST API at the Component level. To generate APIs themselves for specific DataElements, those should be marked with the includeJaxrsConnector option.

The value of the option represents the base path for the Component's API. The default path is /v1, but by specifying a value in the option, a different path can be used. For example, /api/v2 could be used instead.

<options>
<enableJaxrs/>
</options>

Connectors

The REST API itself for a DataElement is defined in a connector class. This class implements methods for each individual REST endpoint which is available for the DataElement. The class is generated in the package api, under the DataElement's package and named DataElementConnector. Where DataElement is the name of the DateElement.

The connector class itself is annotated with a @Path annotation, which defines the relative path of the connector. This path is parsed from the option value supplied in includeJaxrsConnector. Each endpoint method in the connector class is annotated with an annotation which indicates the HTTP method used to address the endpoint, as well as a relative path for the endpoint using the @Path annotation (if any). The path of the endpoints is also parsed out of the includeJaxrsConnector option value, where everything is ignored except for the trailing resource identifier in the value, which is added to the appropriate endpoints (GET for single resource, PUT, PATCH and DELETE). The value given in the individual endpoint options such as exposeGetEndpoint is appended to this path as well, but typically this will rarely be needed.

Option
includeJaxrsConnector DataElement

This option is added to a DataElement to indicate that a REST connector class should be expanded for it. The value of the option should be the path to the path for the DataElement. Common practice is to use the name of the element in its plural form.

Example

DataElement TypeAttribute is typically assigned the path /typeattributes.

caution

When this option is added to a DataElement, there must also be exactly one QuerySearch element linked to that DataElement, which has the option jaxrs.querySearch.

Resource path definition

Each individual endpoint option can define its own path relative to the path of the connector. Some endpoints require a target resource, such as the GET endpoint to retrieve a resource, but also the PATCH, PUT and DELETE endpoints. The name of this resource identifier is typically part of the endpoint's own path. It is possible to add this identifier into the path of the connector. Doing so will indicate to the expanders that this identifier should be used for the path of all previously mentioned endpoints. This also indicates that regardless of its name, this identifier always represents the same thing in each of the respective endpoints.

Example

DataElement TypeAttribute is typically defined with includeJaxrsConnector: /typeattributes. Its PUT endpoint have the option exposePutEndpoint: /{typeAttributeId} and its DELETE endpoint the option exposeDeleteEndpoint: /{typeAttributeId}. Though the name is the same, the expanders can not be sure that typeAttributeId represents the same thing in both the PUT and DELETE endpoints. To indicate this, we define the options as follows: includeJaxrsConnector: /typeattributes/{typeAttributeId}, exposePutEndpoint without a value and exposeDeleteEndpoint without a value.

When the resource path is defined as part of the connector, the connector's path will still be the path without the part containing the tailing resource identifier. What will additionally be generated includes the URL validation implementation and the query filter for the resource identifier.

Multiple path parameters

A path can contain multiple parameters. Excluding for a trailing identifier representing the resource path identifier, all parts of the path, including path variabels will be part of the connector path. These variables will also be added to all of the generated endpoints.

Example

includeJaxrsConnector: /attributes/{attributeId}/typeattributes/{typeAttributeId} will reserve /{typeAttributeId} as the path for the resource endpoints and use /attributes/{attributeId}/typeattributes as the path for the connector, while adding attributeId as a parameter to all expanded endpoint methods.

<options>
<includeJaxrsConnector>/cities/{cityId}</includeJaxrsConnector>
</options>
<options>
<includeJaxrsConnector>/countries/{countryId}/cities/{cityId}</includeJaxrsConnector>
</options>
Option
jaxrs.querySearch QuerySearch

This option marks a QuerySearch model element as the one that will be used by the REST implementation for the DataElement it is linked to.

<options>
<jaxrs.querySearch/>
</options>
Option
externalName DataElement

This option is added to a DataElement to define a name for the element in areas where the name is exposed to the outside world. This means in any externally exposed model and all API documentation.

The value for the option is formatted as Name_PluralName. If the underscore and PluralName is omitted, the Name with a trialing s is used as the plural.

The default when this option is not used is the name of the element for the singular form and the name with a trailing s for the plural form.

<options>
<externalName>Starship</externalName>
</options>
<options>
<externalName>City_Cities</externalName>
</options>
Option
exposeRestField Field

The goal of this option is to provide a default implementation when one wishes to expose a field in a DataElement directly as-is to through the REST API. This provides an implementation, which is fairly inflexible, as it is just a default implementation, but it does cover the majority of use-cases where one wishes to simple expose a field.

It is possible to pass the endpoints on which you wish this to apply if it should not be all of them as a comma-separated list.

<options>
<exposeRestField/>
</options>
<options>
<exposeRestField>GET,PATCH</exposeRestField>
</options>

GET List Endpoint

The GET endpoint to retrieve a list is used to retrieve one or more records from the database. This endpoint supports pagination modeled after to the HAL specification. The data records themselves are retrieved and mapped to a DataElementOutputModel class in the control layer. These objects are then stored in a list in the embedded field (_embedded in JSON) of the PaginatedResponse<T> class. This class also has a links object and page object. The links object contains links dependent on the pagination model, such as a first, next, prev, last and self. The page object contains pagination data, such as the total number of elements (totalElements), the number of pages (totalPages), the current page (number) and number of elements in the page (size).

These endpoints can provide additional search functionality by adding query parameters, which should be passed into the DataElementQueryFilter class, as it should affect the query in the DataElementQuerySearch class.

Option
exposeGetListEndpoint DataElement

This option generates a GET endpoint to retrieve multiple resource in the Connector class for the DataElement, as a method with name get<DataElement>List().

The Option can be supplied with a subpath, that will be appended to the path of the includeJaxrsConnector option.

<options>
<exposeGetListEndpoint/>
</options>
<options>
<exposeGetListEndpoint>/somesubpath</exposeGetListEndpoint>
</options>

Responses

If the request was successful, 200 OK is returned along with a paginated response containing resources as an application/hal+json object. When something goes wrong, a 4xx status is returned in case of a handled error or a 500 status is returned in case of a technical or uncaught error in the application. More information can be found on the error handling page.

Query parameters

To filter elements, a parameter must be added to the custom-getList-parameters anchor. This can be filtered on by adding it to the QueryFilter object that is constructed to perform the query through the QuerySearch system. This can also be automated by adding the option jaxrs.querySearch.exposeFilter to a field in the Querysearch object used for the REST API on the element, which is marked with the option jaxrs.querySearch.

The constraint that applies the filter to the database query must be manually added in the relevant QuerySearch class as to finish the implementation.

Option
jaxrs.querySearch.exposeFilter QueryFilterField

This option will add a parameter for the field to the GET endpoint used to retrieve a list of resources, that is generated using the exposeGetListEndpoint option. This supports all basic types with the exception of the DataRef type added by the expanders for QuerySearch.

<options>
<jaxrs.querySearch.exposeFilter/>
</options>
Example

To filter elements by name, add an optional query parameter in the custom-getList-parameters anchor in the connector's getDateElementDetailsList() method. It should be defined as @QueryParam("name") String name,. In the DataElementQueryFilter class, add the field private String name with both accessor methods.

In the DataElementQuerySearch class, add a constraint to the custom-constraints anchor as:

, when(filter.getName() != null, () ->
equal("o.name", filter.getName(), SPLIT, CONTAINS, CASE_INSENSITIVE)
)

When the name parameter is given, it will be used as a comma-separated list of string values that match the name with case-insensitive contains logic.

Sorting

By default the GETlist endpoint has support for sorting results through the sortby query parameter. The value for the parameter is sorted as follows:

field1[:order],field2[:order],...,fieldN[:order]
  • fieldX is the name of the field, which is mapped in the SortFieldMapper class for the DataElement. The mapping maps the given name to the name of the actual field in the DataElement. The name accepted by the API should typically match the name of a field that is returned in the data for clarity. If the option exposeRestField is used to expose a field, the mapping will be generated automatically.
  • order is an optional value that indicates how the data should be ordered. If provided, it should be asc for ascending ordering or desc for descending ordering. The default if not provided is ascending.
Example
sortby=name,type:asc,index:desc
Option
jaxrs.endpoint.getList.sorting.disable ComponentDataElementCascading

This option disables sorting for the GETlist endpoints if it is defined for the DataElement, as well as generation of the infrastructure for it on the DataElement level.

<options>
<jaxrs.endpoint.getList.sorting.disable/>
</options>

Default order

The QuerySearch instance which is used to retrieve values for the GET call will be assigned the option useDefaultOrder implicitly. This option ensures that results are always sorted by the database identifier field to ensure consistent ordering across all GET operations. If other sorting is defined in the QuerySearch class itself or through the sortby parameter, the ordering by the database identifier is applied after all other ordering is applied.

Additional configuration

Option
jaxrs.endpoint.getList.defaultPage dataElement

Sets the default page for GETlist requests. This marks the first page in the numbering of the pages. If set to 1 (default), the page numbering will start at 1, but if set to 0, the numbering will start at 0. This is also the number of the default apge that will be returned if no page number was specified.

<options>
<jaxrs.endpoint.getList.defaultPage>1</jaxrs.endpoint.getList.defaultPage>
</options>
Option
jaxrs.endpoint.getList.defaultPageSize dataElement

Sets the default page size for GETlist requests. This is the number of elements that will be returned if no size was specified in the call. By default this is set to 10.

<options>
<jaxrs.endpoint.getList.defaultPageSize>10</jaxrs.endpoint.getList.defaultPageSize>
</options>
Option
jaxrs.endpoint.getList.maxPageSize dataElement

Sets the maximum page size for GETlist requests. This is the maximum number of elements that will be returned, regardless of the size was specified in the call. By default there is no maximum.

<options>
<jaxrs.endpoint.getList.maxPageSize>100</jaxrs.endpoint.getList.maxPageSize>
</options>

GET Resource Endpoint

The GET endpoint to retrieve a resource based on a given valid unique identifier for this resource. Typically this identifier is a UUID. A resource is represented by a DataElementOutputModel instance, which is mapped from an internal projection using a DataElementOutputMapper. The mapper maps all fields from the internal representation onto fields in the output model. To represent DataRef objects, every REST element also has a DataElementReferenceModel and to map it a DataElementReferenceMapper.

Option
exposeGetEndpoint DataElement

This option generates a GET endpoint to retrieve a resource in the Connector class for the DataElement, as a method with name get<DataElement>Details().

The Option can be supplied with a subpath, that will be appended to the path of the includeJaxrsConnector option. Ideally the includeJaxrsConnector option will supply the resource identifier for the path, so it can be matched with other endpoints. This means that the preferred usage is without an option value and /{resourceId} being part of the path defined in includeJaxrsConnector.

<options>
<exposeGetEndpoint/>
</options>
<options>
<exposeGetEndpoint>/{resourceId}</exposeGetEndpoint>
</options>

Responses

If the request was successful, 200 OK is returned along with the resource is returned as an application/json object. When something goes wrong, a 4xx status is returned in case of a handled error or a 500 status is returned in case of a technical or uncaught error in the application. More information can be found on the error handling page.

Standard implementation

The REST expanders can generate a default implementation for the GET endpoint. Contrary to the regular implementation, this couples the expansion to the data model, when no custom implementation is needed. The first step to generate this implementation is by adding the resource identifier for the path to the includeJaxrsConnector option. This means the option will have a value such as /dataelements/{dataElementId}, rather than the /{dataElementId} part of the path being provided in the exposeGetEndpoint option. This indicates to the expanders that this identifier represents the same thing in every endpoint that takes a resource identifier. Also that this identifier uniquely represents a resource for this DataElement.

Every field that should be exposed as-is through the GET endpoint, should have the option exposeRestField. This indicates to the expanders that this field does not require any custom mapping and can just be exposed directly. This works for both valuefields and linkfields. In case of a linkfield, the output of the endpoint will contain a reference object that represents the linked resource.

Additional configuration

Option
noRestExcludeNull ComponentDataElement

By default, all fields which contain a null value in GET calls are not listed in the payload. This option will enable these fields being returned with the value null instead.

<options>
<noRestExcludeNull/>
</options>
Option
jaxrs.querySearch.projection DataElement

This option can be used to specify what projection should be returned from the data layer to the GET endpoints. The option defaults to jaxrs.querySearch.projection: details as the projection used should contain at least all fields which are being exposed through the REST API.

<options>
<jaxrs.querySearch.projection/>
</options>

POST Endpoint

The POST endpoint is used to create a new resource. When the endpoint is called, input data should be provided in JSON format, which is serialized to the DataElementPostInputModel class. This in turn is mapped by the DataElementPostInputMapper to the DataElementCommand.CreateDataElement class.

warning

To correctly generate this endpoint, you should always defined a command with the option jaxrs.command.create, as this will be used to both transport the input data and execute the creation of the resource.

Option
exposePostEndpoint DataElement

This option generates a POST endpoint in the Connector class for the DataElement, as a method with name create<DataElement>(). If a DataCommand with the option jaxrs.command.create is defined, it will use that command to transport the data from the endpoint and execute the creation of resources.

The Option can be supplied with a subpath, that will be appended to the path of the includeJaxrsConnector option.

<options>
<exposePostEndpoint/>
</options>
<options>
<exposePostEndpoint>/somesubpath</exposePostEndpoint>
</options>
Option
jaxrs.command.create DataCommand

This option must be added to a command that is intended to be used to process the call to the POST endpoint.

<options>
<jaxrs.command.create/>
</options>

Responses

If the request was successful, 201 Created is returned along with a application/json object containing the identifier which represents the resource and a Location header, containing the url to the resource. When something goes wrong, a 4xx status is returned in case of a handled error or a 500 status is returned in case of a technical or uncaught error in the application. More information can be found on the error handling page.

Example return payload
{
"id": "55889f12-5488-480e-a967-c8aaf395f4f5"
}

Standard implementation

The REST expanders can generate a default implementation for the POST endpoint. Most of the code for this endpoint is always generated, but given that fields have the option exposeRestField and a field with the same name and type is present in the command, it will add these fields to the input model for the endpoint. One exception is that when the field is a linkfield, the field in the command should be of type String, so a reference which should be the functional key, can be passed in the model. Code will be generated that will automatically resolve this reference.

When the enableValidation option is active on the component, the REST expanders will also generate a DataElementPostInputValidator class in the control layer, which verifies the data given in the input model. These checks include checking that required data is present. It will also generate a DataElementCreateDataValidator class in the logic layer, which will check the data against the database, for checks such as exists and unique.

PUT Endpoint

The PUT endpoint is used to update an existing resource. It should overwrite all fields of a resource if they are specified in the endpoint, even if they are not filled out in the request. When the endpoint is called, input data should be provided in JSON format, which is serialized to the DataElementPutInputModel class. This in turn is mapped by the DataElementPutInputMapper to the DataElementCommand.ModifyDataElement class.

warning

To correctly generate this endpoint, you should always defined a command with the option jaxrs.command.modify, as this will be used to both transport the input data and execute the modification of the resource.

Option
exposePutEndpoint DataElement

This option generates a PUT endpoint in the Connector class for the DataElement, as a method with name put<DataElement>(). If a DataCommand with the option jaxrs.command.modify is defined, it will use that command to transport the data from the endpoint and execute the modification of resources.

The Option can be supplied with a subpath, that will be appended to the path of the includeJaxrsConnector option. Ideally the includeJaxrsConnector option will supply the resource identifier for the path, so it can be matched with other endpoints. This means that the preferred usage is without an option value and /{resourceId} being part of the path defined in includeJaxrsConnector.

<options>
<exposePutEndpoint/>
</options>
<options>
<exposePutEndpoint>/{resourceId}</exposePutEndpoint>
</options>
Option
jaxrs.command.modify DataCommand

This option must be added to a command that is intended to be used to process the call to the PUT endpoint.

<options>
<jaxrs.command.modify/>
</options>

Responses

If the request was successful, 204 No Context is returned and the resource will be modified. When something goes wrong, a 4xx status is returned in case of a handled error or a 500 status is returned in case of a technical or uncaught error in the application. More information can be found on the error handling page.

Standard implementation

The REST expanders can generate a default implementation for the PUT endpoint. Most of the code for this endpoint is always generated, but given that fields have the option exposeRestField and a field with the same name and type is present in the command, it will add these fields to the input model for the endpoint. One exception is that when the field is a linkfield, the field in the command should be of type String, so a reference which should be the functional key, can be passed in the model. Code will be generated that will automatically resolve this reference.

When the enableValidation option is active on the component, the REST expanders will also generate a DataElementPutInputValidator class in the control layer, which verifies the data given in the input model. These checks include checking that required data is present. It will also generate a DataElementModifyDataValidator class in the logic layer, which will check the data against the database, for checks such as exists and unique.

PATCH Endpoint

The PATCH endpoint is used to update an existing resource. It will update all fields of a resource that are specified in the payload sent along with a request to the endpoint. When the endpoint is called, input data should be provided in JSON format, which is serialized to the DataElementPatchInputModel class. This in turn is mapped by the DataElementPatchInputMapper to the DataElementCommand.UpdateDataElement class.

warning

To correctly generate this endpoint, you should always defined a command with the option jaxrs.command.update, as this will be used to both transport the input data and execute the update of the resource.

Option
exposePatchEndpoint DataElement

This option generates a PATCH endpoint in the Connector class for the DataElement, as a method with name patch<DataElement>(). If a DataCommand with the option jaxrs.command.update is defined, it will use that command to transport the data from the endpoint and execute the updating of resources.

The Option can be supplied with a subpath, that will be appended to the path of the includeJaxrsConnector option. Ideally the includeJaxrsConnector option will supply the resource identifier for the path, so it can be matched with other endpoints. This means that the preferred usage is without an option value and /{resourceId} being part of the path defined in includeJaxrsConnector.

<options>
<exposePatchEndpoint/>
</options>
<options>
<exposePatchEndpoint>/{resourceId}</exposePatchEndpoint>
</options>
Option
jaxrs.command.update DataCommand

This option must be added to a command that is intended to be used to process the call to the PATCH endpoint.

<options>
<jaxrs.command.update/>
</options>

Responses

If the request was successful, 204 No Context is returned and the resource will be updated. When something goes wrong, a 4xx status is returned in case of a handled error or a 500 status is returned in case of a technical or uncaught error in the application. More information can be found on the error handling page.

Standard implementation

The REST expanders can generate a default implementation for the PATCH endpoint. Most of the code for this endpoint is always generated, but given that fields have the option exposeRestField and a field with the same name and type is present in the command, it will add these fields to the input model for the endpoint. One exception is that when the field is a linkfield, the field in the command should be of type String, so a reference which should be the functional key, can be passed in the model. Code will be generated that will automatically resolve this reference.

When the enableValidation option is active on the component, the REST expanders will also generate a DataElementPatchInputValidator class in the control layer, which verifies the data given in the input model. These checks include checking that required data is present. It will also generate a DataElementUpdateDataValidator class in the logic layer, which will check the data against the database, for checks such as exists and unique.

DELETE Endpoint

The DELETE endpoint is used to remove an existing resource. After successfully calling this endpoint with a valid resource identifier, the resource it represents will no longer exist.

warning

To correctly generate this endpoint, you should always defined a command with the option jaxrs.command.remove, as this will be used to both transport the resource identifier and execute the removal of the resource.

Option
exposeDeleteEndpoint DataElement

This option generates a DELETE endpoint in the Connector class for the DataElement, as a method with name delete<DataElement>(). If a DataCommand with the option jaxrs.command.remove is defined, it will use that command to transport the data from the endpoint and execute the creation of resources.

The Option can be supplied with a subpath, that will be appended to the path of the includeJaxrsConnector option. Ideally the includeJaxrsConnector option will supply the resource identifier for the path, so it can be matched with other endpoints. This means that the preferred usage is without an option value and /{resourceId} being part of the path defined in includeJaxrsConnector.

<options>
<exposeDeleteEndpoint/>
</options>
<options>
<exposeDeleteEndpoint>/{resourceId}</exposeDeleteEndpoint>
</options>
Option
jaxrs.command.remove DataCommand

This option must be added to a command that is intended to be used to process the call to the DELETE endpoint.

<options>
<jaxrs.command.remove/>
</options>

Responses

If the request was successful, 204 No Context is returned and the resource will be deleted. When something goes wrong, a 4xx status is returned in case of a handled error or a 500 status is returned in case of a technical or uncaught error in the application. More information can be found on the error handling page.

Standard implementation

The REST expanders can generate a default implementation for the DELETE endpoint which will perform the delete operation when given a valid resource identifier.

File IO Endpoints

It is possible to expand endpoints for file IO operations (since rest-expanders version 4.24.0). This refers to file uploads and downloads.

In this implementation we consider file resources to be a special case of a resource that can be linked to a regular api-accessible resource on the server. These links to files are represented by fields in a rest resource. It is possible to use both value- and linkfields to represent files.

As files are considered to be individual resources, they must be uploaded independently from the rest resources and then linked by reference on create or modify.

The file APIs take into account three different concepts that can be mixed freely:

  • The endpoints to upload and/or download a file.
  • The link between a regular resource and a file.
  • The default implementation of the two previous items for specific fields.

Upload endpoints

Option
svcapi.endpoint.upload Field

This option generates a POST endpoint in the Connector class for the DataElement to upload a file in function of the field it is applied to. The field will be marked with the tag #svcapi.endpoint.io.upload to indicate that it has an upload endpoint. This also implies that this field represents a file resource, for which the tag #svcapi.field.io will be applied.

<options>
<svcapi.endpoint.upload/>
</options>

The option svcapi.endpoint.upload is used to add an upload endpoint to a Field. The upload endpoint will accept the incoming file and write it to a temporary location on the server. It is then read from that location to store it in its final location. Apache Tika is used to try to identify the type of the file and the size is also automatically determined. This information can then be used by a further implementation to store the file.

The path of an upload endpoint for a field is currently defined as ../<connectorBasePath>/upload/<fieldName>. The connectorBasePath in this example is the connector path without the trailing path parameter.

When a file is successfully uploaded, a unique identifier is returned in the NS-File-Upload-Id header. This identifier can be used to link the file resource to a resource of the DataElement the Field belongs to.

Standard implementation

Currently a default implementation is available for links to assets:Asset with the rest-assets-expanders resource. This will store the file as a new Asset and the functional key (file identifier) of that Asset is returned in the NS-File-Upload-Id header.

To activate the default implementation, the Field must have the option exposeRestField without value or containing the value POST_FILE alongside any other endpoints defined in the value.

Download endpoints

Option
svcapi.endpoint.download Field

This option generates a GET endpoint in the Connector class for the DataElement to download a file linked to a field in a specific DataElement resource. The field will be marked with the tag #svcapi.endpoint.io.download to indicate that it has a download endpoint. This also implies that this field represents a file resource, for which the tag #svcapi.field.io will be applied.

<options>
<svcapi.endpoint.download/>
</options>

The option svcapi.endpoint.download is used to add a download endpoint to a Field. The download endpoint will transfer a file linked to the field depending on the endpoint implementation. If no file is linked to the field, a 404 Not Found error is returned by the API.

The path of an upload endpoint for a field is currently defined as ../<connectorPath>/download/<fieldName>. The connectorPath in this example is the connector path without the trailing path parameter.

Standard implementation

Currently a default implementation is available for links to assets:Asset with the rest-assets-expanders resource. This will retrieve the file from a linked asset and provide it as a download of the relevant content type as it was stored for that asset.

To activate the default implementation, the Field must have the option exposeRestField without value or containing the value GET_FILE alongside any other endpoints defined in the value.

Files can be represented by a ValueField or a LinkField, depending on the implementation. When a field represents a file, the tag #svcapi.field.io will be applied to the field. This can be provided by a specific implementation and it is also added when an upload or download endpoint is added to the field.

A file reference is a JSON object containing up to three properties:

  • resourceUri: An optional property that is only present when a download endpoint exists for the resource, with the specific uri to the endpoint that downloads the references resource.
  • identifier: A unique identifier that can be used to identify the file in (at minimum) the context of this field.
  • fileName: An optional property that contains the name of the file if provided by the implementation.
Example resource with file field

In the following example resource, birthCertificate represents a file resource.

{
"name": "Snickers",
"uuid": "f9020d14-b1ab-4de3-99a2-f0a2e5a8c71d",
"birthCertificate": {
"resourceUri": "http://localhost:8080/restexample/v1/cats/f9020d14-b1ab-4de3-99a2-f0a2e5a8c71d/download/birthCertificate",
"identifier": "d8227d40-4e8b-4b7f-baf4-52bb8a051e26",
"fileName": "snickers-haz-cheeseburger.jpeg"
},
"breed": {
"resourceUri": "http://localhost:8080/restexample/v1/catbreeds/Maine%20Coon",
"name": "Maine Coon"
}
}