diff --git a/.changeset/soft-trees-perform.md b/.changeset/soft-trees-perform.md
new file mode 100644
index 000000000..1d4ccb624
--- /dev/null
+++ b/.changeset/soft-trees-perform.md
@@ -0,0 +1,6 @@
+---
+'@gitbook/react-openapi': minor
+'gitbook': minor
+---
+
+Fix internal properties appearing in OpenAPI docs.
diff --git a/packages/react-openapi/src/OpenAPICodeSample.tsx b/packages/react-openapi/src/OpenAPICodeSample.tsx
index 3174d3711..19542ef31 100644
--- a/packages/react-openapi/src/OpenAPICodeSample.tsx
+++ b/packages/react-openapi/src/OpenAPICodeSample.tsx
@@ -8,6 +8,7 @@ import { getServersURL } from './OpenAPIServerURL';
import { ScalarApiButton } from './ScalarApiButton';
import { OpenAPIContextProps } from './types';
import { noReference } from './utils';
+import { stringifyOpenAPI } from './stringifyOpenAPI';
/**
* Display code samples to execute the operation.
@@ -34,7 +35,7 @@ export function OpenAPICodeSample(props: {
: undefined;
if (example !== undefined) {
headersObject[param.name] =
- typeof example !== 'string' ? JSON.stringify(example) : example;
+ typeof example !== 'string' ? stringifyOpenAPI(example) : example;
}
} else if (param.in === 'query' && param.required) {
const example = param.schema
diff --git a/packages/react-openapi/src/OpenAPIResponseExample.tsx b/packages/react-openapi/src/OpenAPIResponseExample.tsx
index f4758c485..12705a8ae 100644
--- a/packages/react-openapi/src/OpenAPIResponseExample.tsx
+++ b/packages/react-openapi/src/OpenAPIResponseExample.tsx
@@ -4,6 +4,7 @@ import { OpenAPIOperationData } from './fetchOpenAPIOperation';
import { generateSchemaExample } from './generateSchemaExample';
import { OpenAPIContextProps } from './types';
import { createStateKey, noReference } from './utils';
+import { stringifyOpenAPI } from './stringifyOpenAPI';
/**
* Display an example of the response content.
@@ -63,7 +64,9 @@ export function OpenAPIResponseExample(props: {
body: (
diff --git a/packages/react-openapi/src/OpenAPISchema.tsx b/packages/react-openapi/src/OpenAPISchema.tsx
index 6060cf6b6..dbdada966 100644
--- a/packages/react-openapi/src/OpenAPISchema.tsx
+++ b/packages/react-openapi/src/OpenAPISchema.tsx
@@ -7,6 +7,7 @@ import { Markdown } from './Markdown';
import { SYMBOL_REF_RESOLVED } from './resolveOpenAPIPath';
import { OpenAPIClientContext } from './types';
import { noReference } from './utils';
+import { stringifyOpenAPI } from './stringifyOpenAPI';
type CircularRefsIds = Map;
@@ -101,7 +102,7 @@ export function OpenAPISchemaProperty(
) : null}
{shouldDisplayExample(schema) ? (
- Example: {JSON.stringify(schema.example)}
+ Example: {stringifyOpenAPI(schema.example)}
) : null}
{schema.pattern ? (
diff --git a/packages/react-openapi/src/code-samples.ts b/packages/react-openapi/src/code-samples.ts
index fd921ce8a..2baae2f44 100644
--- a/packages/react-openapi/src/code-samples.ts
+++ b/packages/react-openapi/src/code-samples.ts
@@ -1,3 +1,5 @@
+import { stringifyOpenAPI } from './stringifyOpenAPI';
+
export interface CodeSampleInput {
method: string;
url: string;
@@ -24,11 +26,11 @@ export const codeSampleGenerators: CodeSampleGenerator[] = [
method: '${method.toUpperCase()}',\n`;
if (headers) {
- code += indent(`headers: ${JSON.stringify(headers, null, 2)},\n`, 4);
+ code += indent(`headers: ${stringifyOpenAPI(headers, null, 2)},\n`, 4);
}
if (body) {
- code += indent(`body: JSON.stringify(${JSON.stringify(body, null, 2)}),\n`, 4);
+ code += indent(`body: JSON.stringify(${stringifyOpenAPI(body, null, 2)}),\n`, 4);
}
code += `});\n`;
@@ -59,7 +61,7 @@ export const codeSampleGenerators: CodeSampleGenerator[] = [
lines.push(`'${url}'`);
if (body) {
- lines.push(`-d '${JSON.stringify(body)}'`);
+ lines.push(`-d '${stringifyOpenAPI(body)}'`);
}
return lines.map((line, index) => (index > 0 ? indent(line, 2) : line)).join(separator);
@@ -74,10 +76,10 @@ export const codeSampleGenerators: CodeSampleGenerator[] = [
code += `response = requests.${method.toLowerCase()}(\n`;
code += indent(`"${url}",\n`, 4);
if (headers) {
- code += indent(`headers=${JSON.stringify(headers)},\n`, 4);
+ code += indent(`headers=${stringifyOpenAPI(headers)},\n`, 4);
}
if (body) {
- code += indent(`json=${JSON.stringify(body)}\n`, 4);
+ code += indent(`json=${stringifyOpenAPI(body)}\n`, 4);
}
code += ')\n';
code += `data = response.json()`;
@@ -93,7 +95,7 @@ export const codeSampleGenerators: CodeSampleGenerator[] = [
if (body) {
// if we had a body add a content length header
- const bodyContent = body ? JSON.stringify(body) : '';
+ const bodyContent = body ? stringifyOpenAPI(body) : '';
// handle unicode chars with a text encoder
const encoder = new TextEncoder();
@@ -115,7 +117,7 @@ export const codeSampleGenerators: CodeSampleGenerator[] = [
.join('\n') + '\n'
: '';
- const bodyString = body ? `\n${JSON.stringify(body, null, 2)}` : '';
+ const bodyString = body ? `\n${stringifyOpenAPI(body, null, 2)}` : '';
const httpRequest = `${method.toUpperCase()} ${decodeURI(path)} HTTP/1.1
Host: ${host}
diff --git a/packages/react-openapi/src/resolveOpenAPIPath.ts b/packages/react-openapi/src/resolveOpenAPIPath.ts
index cc247476e..6570fa337 100644
--- a/packages/react-openapi/src/resolveOpenAPIPath.ts
+++ b/packages/react-openapi/src/resolveOpenAPIPath.ts
@@ -1,6 +1,6 @@
import { OpenAPIFetcher } from './types';
-const SYMBOL_MARKDOWN_PARSED = '__$markdownParsed';
+export const SYMBOL_MARKDOWN_PARSED = '__$markdownParsed';
export const SYMBOL_REF_RESOLVED = '__$refResolved';
/**
diff --git a/packages/react-openapi/src/stringifyOpenAPI.ts b/packages/react-openapi/src/stringifyOpenAPI.ts
new file mode 100644
index 000000000..99186e550
--- /dev/null
+++ b/packages/react-openapi/src/stringifyOpenAPI.ts
@@ -0,0 +1,20 @@
+import { SYMBOL_MARKDOWN_PARSED, SYMBOL_REF_RESOLVED } from './resolveOpenAPIPath';
+
+/**
+ * Stringify an OpenAPI object. Same API as JSON.stringify.
+ */
+export function stringifyOpenAPI(body: unknown, transformer?: null, indent?: number): string {
+ return JSON.stringify(
+ body,
+ (_key, value) => {
+ if (value && !Array.isArray(value) && typeof value === 'object') {
+ // Extract out internal keys used in parsing
+ const { [SYMBOL_MARKDOWN_PARSED]: _, [SYMBOL_REF_RESOLVED]: __, ...rest } = value;
+ return rest;
+ }
+
+ return value;
+ },
+ indent,
+ );
+}