Skip to content

Commit b1258ca

Browse files
authored
fix: nested examples in OpenAPI schemas for request body & response (#772)
1 parent d960bcb commit b1258ca

File tree

3 files changed

+899
-213
lines changed

3 files changed

+899
-213
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,7 @@ Will generate this in the OpenAPI v3 schema's `path`:
10001000
"foo": { "type": "string" },
10011001
"bar": { "type": "string" }
10021002
},
1003-
"examples": [{ "foo": "bar", "bar": "baz" }]
1003+
"example": { "foo": "bar", "bar": "baz" }
10041004
}
10051005
}
10061006
},

lib/spec/openapi/utils.js

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,40 @@ function plainJsonObjectToOpenapi3 (container, jsonSchema, externalSchemas, secu
231231
})
232232
}
233233

234+
const schemaTypeToNestedSchemas = {
235+
object: (schema) => {
236+
return [
237+
...Object.values(schema.properties || {}),
238+
...Object.values(schema.patternProperties || {}),
239+
...Object.values(schema.additionalProperties || {})
240+
]
241+
},
242+
array: (schema) => {
243+
return [
244+
...(schema.items ? [schema.items] : []),
245+
...(schema.contains ? [schema.contains] : [])
246+
]
247+
}
248+
}
249+
250+
function resolveSchemaExamples (schema) {
251+
const example = schema[xExamples] ?? schema.examples?.[0]
252+
if (typeof example !== 'undefined') {
253+
schema.example = example
254+
}
255+
delete schema[xExamples]
256+
delete schema.examples
257+
}
258+
259+
function resolveSchemaExamplesRecursive (schema) {
260+
resolveSchemaExamples(schema)
261+
const getNestedSchemas = schemaTypeToNestedSchemas[schema.type]
262+
const nestedSchemas = getNestedSchemas?.(schema) ?? []
263+
for (const nestedSchema of nestedSchemas) {
264+
resolveSchemaExamplesRecursive(nestedSchema)
265+
}
266+
}
267+
234268
function schemaToMedia (schema) {
235269
const media = { schema }
236270

@@ -251,13 +285,19 @@ function schemaToMedia (schema) {
251285
return media
252286
}
253287

288+
function schemaToMediaRecursive (schema) {
289+
const media = schemaToMedia(schema)
290+
resolveSchemaExamplesRecursive(schema)
291+
return media
292+
}
293+
254294
function resolveBodyParams (body, schema, consumes, ref) {
255295
const resolved = transformDefsToComponents(ref.resolve(schema))
256296
if ((Array.isArray(consumes) && consumes.length === 0) || consumes === undefined) {
257297
consumes = ['application/json']
258298
}
259299

260-
const media = schemaToMedia(resolved)
300+
const media = schemaToMediaRecursive(resolved)
261301
consumes.forEach((consume) => {
262302
body.content[consume] = media
263303
})
@@ -346,7 +386,7 @@ function resolveResponse (fastifyResponseJson, produces, ref) {
346386

347387
delete resolved[xResponseDescription]
348388

349-
const media = schemaToMedia(resolved)
389+
const media = schemaToMediaRecursive(resolved)
350390

351391
for (const produce of produces) {
352392
content[produce] = media

0 commit comments

Comments
 (0)