diff --git a/.changeset/many-tomatoes-bathe.md b/.changeset/many-tomatoes-bathe.md
new file mode 100644
index 0000000000..38260be329
--- /dev/null
+++ b/.changeset/many-tomatoes-bathe.md
@@ -0,0 +1,7 @@
+---
+'@commercetools-docs/gatsby-theme-api-docs': patch
+'@commercetools-website/api-docs-smoke-test': patch
+'@commercetools-api-specs/test': patch
+---
+
+Add support for primitive and generic JSON types in API request and response
diff --git a/api-specs/test/api.raml b/api-specs/test/api.raml
index a540dcd3c2..4510938412 100644
--- a/api-specs/test/api.raml
+++ b/api-specs/test/api.raml
@@ -475,6 +475,21 @@ uses:
type: object
example: !include examples/action-success.json
+ /json-serializable-primitive-type:
+ put:
+ description: Use the PUT method to write data to a backend system. Any JSON serializable payload is accepted. The following request example adds a product to a cart. For the response, we recommend to use standard HTTP codes and `application/json` encoded content. The response will be structured [as defined by the `body` property of the action](/). The following response example contains the updated cart information, which includes the added product.
+ body:
+ application/json:
+ type: object
+ example: !include examples/json-serializable-primitive-object.json
+ responses:
+ 200:
+ description: We recommend to use standard HTTP response codes and `application/json` encoded content. The response will look like the response you have declared in your action. As an example we will fetch the cart.
+ body:
+ application/json:
+ type: any
+ example: !include examples/json-serializable-primitive-raw.json
+
# /resourceWithHeaders:
# description: Tests use of specific headers.
diff --git a/api-specs/test/examples/json-serializable-primitive-object.json b/api-specs/test/examples/json-serializable-primitive-object.json
new file mode 100644
index 0000000000..0967ef424b
--- /dev/null
+++ b/api-specs/test/examples/json-serializable-primitive-object.json
@@ -0,0 +1 @@
+{}
diff --git a/api-specs/test/examples/json-serializable-primitive-raw.json b/api-specs/test/examples/json-serializable-primitive-raw.json
new file mode 100644
index 0000000000..d3e505fbc8
--- /dev/null
+++ b/api-specs/test/examples/json-serializable-primitive-raw.json
@@ -0,0 +1 @@
+"raw string"
diff --git a/packages/gatsby-theme-api-docs/src/components/resource/method/request-representation.js b/packages/gatsby-theme-api-docs/src/components/resource/method/request-representation.js
index d5e3525e25..4e160e02d3 100644
--- a/packages/gatsby-theme-api-docs/src/components/resource/method/request-representation.js
+++ b/packages/gatsby-theme-api-docs/src/components/resource/method/request-representation.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import styled from '@emotion/styled';
import SpacingsStack from '@commercetools-uikit/spacings-stack';
import SpacingsInline from '@commercetools-uikit/spacings-inline';
-import { designSystem } from '@commercetools-docs/ui-kit';
+import { designSystem, Markdown } from '@commercetools-docs/ui-kit';
import {
useTypeLocations,
locationForType,
@@ -12,6 +12,7 @@ import renderTypeAsLink from '../../../utils/render-type-as-link';
import ApiTypeByKey from '../../type/type-by-api-key';
import Title from './title';
import ContentType from './highlights';
+import { getDescriptionIfPrimitiveType } from '../../type/type';
const RequestRepresentation = (props) => {
const typeLocations = useTypeLocations();
@@ -21,6 +22,19 @@ const RequestRepresentation = (props) => {
typeLocations
);
+ let primitiveJSONType;
+
+ if (
+ !requestRepresentationLocation &&
+ props.contentType &&
+ props.contentType.includes('application/json')
+ ) {
+ primitiveJSONType = getDescriptionIfPrimitiveType(
+ 'application/json',
+ props.apiType
+ );
+ }
+
const ContentTypeRow = styled.div`
display: flex;
align-items: center;
@@ -46,9 +60,13 @@ const RequestRepresentation = (props) => {
})}
The file to upload
- ) : requestRepresentationLocation ? (
+ ) : requestRepresentationLocation || primitiveJSONType ? (
- {renderTypeAsLink(props.apiKey, props.apiType, typeLocations)}
+ {primitiveJSONType ? (
+ {primitiveJSONType}
+ ) : (
+ renderTypeAsLink(props.apiKey, props.apiType, typeLocations)
+ )}
as
{props.contentType}
@@ -56,6 +74,7 @@ const RequestRepresentation = (props) => {
{props.contentType}
{
apiKey,
response.body.applicationjson.type,
typeLocations,
- response.description
+ response.description,
+ contentType
)}
{contentType.length > 0 && (
<>
diff --git a/packages/gatsby-theme-api-docs/src/components/type/type.js b/packages/gatsby-theme-api-docs/src/components/type/type.js
index 5aebdcb8d1..c73e98db54 100644
--- a/packages/gatsby-theme-api-docs/src/components/type/type.js
+++ b/packages/gatsby-theme-api-docs/src/components/type/type.js
@@ -12,13 +12,44 @@ import Enum from './enum';
import Properties from './properties/properties';
import Examples from './examples';
+const contentTypeToPrimitiveMap = {
+ 'application/json': {
+ number: 'Any JSON "number"',
+ any: 'Any valid JSON',
+ object: 'Any JSON "object"',
+ boolean: 'Any JSON "boolean"',
+ string: 'Any JSON "string"',
+ array: 'Any JSON "array"',
+ },
+};
+
+export const getDescriptionIfPrimitiveType = (contentType, type) =>
+ contentTypeToPrimitiveMap[contentType] &&
+ contentTypeToPrimitiveMap[contentType][type];
+
const ApiType = (props) => {
- const matchedApiType = props.apiTypes.find((apiType) => {
+ console.log(props);
+ let matchedApiType = props.apiTypes.find((apiType) => {
return (
apiType.apiKey === props.apiKey && apiType.displayName === props.type
);
});
+ if (!matchedApiType) {
+ if (props.contentType && props.contentType.includes('application/json')) {
+ const primitiveTypeDescription = getDescriptionIfPrimitiveType(
+ 'application/json',
+ props.type
+ );
+ if (primitiveTypeDescription) {
+ matchedApiType = {
+ displayName: props.type,
+ description: primitiveTypeDescription,
+ };
+ }
+ }
+ }
+
if (!matchedApiType) {
return reportError(
`Type with name '${props.type}' not found in '${props.apiKey}' API`
@@ -92,6 +123,7 @@ ApiType.propTypes = {
]),
doNotRenderExamples: PropTypes.bool,
hideInheritedProperties: PropTypes.bool,
+ contentType: PropTypes.arrayOf(PropTypes.string),
};
export default ApiType;
diff --git a/packages/gatsby-theme-api-docs/src/utils/render-type-as-link.js b/packages/gatsby-theme-api-docs/src/utils/render-type-as-link.js
index 59ffbe7e97..bee3c7f86d 100644
--- a/packages/gatsby-theme-api-docs/src/utils/render-type-as-link.js
+++ b/packages/gatsby-theme-api-docs/src/utils/render-type-as-link.js
@@ -1,20 +1,36 @@
import React from 'react';
import { Link } from '@commercetools-docs/gatsby-theme-docs';
-import { markdownFragmentToReact } from '@commercetools-docs/ui-kit';
+import { markdownFragmentToReact, Markdown } from '@commercetools-docs/ui-kit';
import { locationForType } from '../hooks/use-type-locations';
+import { getDescriptionIfPrimitiveType } from '../components/type/type';
-function renderTypeAsLink(apiKey, type, typeLocations, description) {
+function renderTypeAsLink(
+ apiKey,
+ type,
+ typeLocations,
+ description,
+ contentType
+) {
const typeLocation = locationForType(apiKey, type, typeLocations);
- const originalTypeLocation = typeLocation ? typeLocation.url : '';
+ const originalTypeLocation = typeLocation ? typeLocation.url : undefined;
- return originalTypeLocation ? (
- {type}
- ) : description ? (
- markdownFragmentToReact(description)
- ) : (
- type
- );
-}
+ let primitiveJsonType;
+ if (
+ !originalTypeLocation &&
+ Array.isArray(contentType) &&
+ contentType.includes('application/json')
+ ) {
+ primitiveJsonType = getDescriptionIfPrimitiveType('application/json', type);
+ }
+ if (originalTypeLocation) {
+ return {type};
+ } else if (primitiveJsonType) {
+ return {primitiveJsonType};
+ } else if (description) {
+ return markdownFragmentToReact(description);
+ }
+ return type;
+}
export default renderTypeAsLink;
diff --git a/websites/api-docs-smoke-test/src/content/endpoints/endpoints-for-resource.mdx b/websites/api-docs-smoke-test/src/content/endpoints/endpoints-for-resource.mdx
index d00473a307..76a3052782 100644
--- a/websites/api-docs-smoke-test/src/content/endpoints/endpoints-for-resource.mdx
+++ b/websites/api-docs-smoke-test/src/content/endpoints/endpoints-for-resource.mdx
@@ -28,3 +28,7 @@ import { ApiEndpointsForResource } from "/shortcodes"
# /{projectKey}/resource/namespace-action-with-example
+
+# /{projectKey}/resource/json-serializable-primitive-type
+
+