Skip to content

Support allOf, anyOf, and oneOf schemas with properties in array item #1156

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions demo/examples/tests/allOf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,76 @@ paths:
items:
$ref: "#/components/schemas/Book"

/allof-with-properties-in-array-item:
get:
tags:
- allOf
summary: allOf with Properties in Array Item
description: |
A list of books demonstrating allOf with properties in array item.

Schema:
```yaml
type: array
items:
$ref: '#/components/schemas/Book'
```

Schema Components:
```yaml
BookBase:
type: object
required:
- id
- title
- author
properties:
id:
type: integer
format: int64
description: Unique identifier for the book
title:
type: string
description: The title of the book
author:
type: string
description: The author of the book

AdditionalBookInfo:
type: object
properties:
publishedDate:
type: string
format: date
description: The date the book was published
genre:
type: string
description: The genre of the book
tags:
type: array
items:
type: string
description: Tags associated with the book

CategorizedBook:
allOf:
- $ref: '#/components/schemas/BookBase'
- $ref: '#/components/schemas/AdditionalBookInfo'
properties:
category:
type: string
description: The category of the book
```
responses:
"200":
description: A list of books
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/CategorizedBook"

/allof-nested:
get:
tags:
Expand Down Expand Up @@ -320,12 +390,15 @@ components:
type: integer
format: int64
description: Unique identifier for the book
example: 1234567890
title:
type: string
description: The title of the book
example: "The Great Gatsby"
author:
type: string
description: The author of the book
example: "F. Scott Fitzgerald"

AdditionalBookInfo:
type: object
Expand All @@ -334,16 +407,29 @@ components:
type: string
format: date
description: The date the book was published
example: "2021-01-01"
genre:
type: string
description: The genre of the book
example: "Fiction"
tags:
type: array
items:
type: string
description: Tags associated with the book
example: ["Fiction", "Mystery"]

Book:
allOf:
- $ref: "#/components/schemas/BookBase"
- $ref: "#/components/schemas/AdditionalBookInfo"

CategorizedBook:
allOf:
- $ref: "#/components/schemas/BookBase"
- $ref: "#/components/schemas/AdditionalBookInfo"
properties:
category:
type: string
description: The category of the book
example: "Fiction"
60 changes: 60 additions & 0 deletions demo/examples/tests/anyOf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,63 @@ paths:
- type: boolean
title: A boolean
title: A string or integer, or a boolean

/anyof-with-properties-in-array-item:
get:
tags:
- anyOf
summary: anyOf with Properties in Array Item
description: |
Schema:
```yaml
type: array
items:
type: object
anyOf:
- type: object
title: Item
properties:
orderNo:
type: string
example: "123456"
- type: object
title: Error
properties:
error:
type: string
example: "Invalid order number"
properties:
name:
type: string
example: pencil
required:
- orderNo
```
responses:
"200":
description: Successful response
content:
application/json:
schema:
type: array
items:
type: object
anyOf:
- type: object
title: Item
properties:
orderNo:
type: string
example: "123456"
- type: object
title: Error
properties:
error:
type: string
example: "Invalid order number"
properties:
name:
type: string
example: pencil
required:
- orderNo
60 changes: 60 additions & 0 deletions demo/examples/tests/oneOf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,63 @@ paths:
requiredPropB:
type: number
required: ["requiredPropB"]

/oneof-with-properties-in-array-item:
get:
tags:
- oneOf
summary: oneOf with Properties in Array Item
description: |
Schema:
```yaml
type: array
items:
type: object
oneOf:
- type: object
title: Item
properties:
orderNo:
type: string
example: "123456"
- type: object
title: Error
properties:
error:
type: string
example: "Invalid order number"
properties:
name:
type: string
example: pencil
required:
- orderNo
```
responses:
"200":
description: Successful response
content:
application/json:
schema:
type: array
items:
type: object
oneOf:
- type: object
title: Item
properties:
orderNo:
type: string
example: "123456"
- type: object
title: Error
properties:
error:
type: string
example: "Invalid order number"
properties:
name:
type: string
example: pencil
required:
- orderNo
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,11 @@ export const sampleRequestFromSchema = (schema: SchemaObject = {}): any => {

if (type === "array") {
if (Array.isArray(items?.anyOf)) {
return items?.anyOf.map((item: any) => sampleRequestFromSchema(item));
return processArrayItems(items, "anyOf");
}

if (Array.isArray(items?.oneOf)) {
return items?.oneOf.map((item: any) => sampleRequestFromSchema(item));
return processArrayItems(items, "oneOf");
}

return normalizeArray(sampleRequestFromSchema(items));
Expand Down Expand Up @@ -233,3 +233,26 @@ function normalizeArray(arr: any) {
}
return [arr];
}

function processArrayItems(
items: SchemaObject,
schemaType: "anyOf" | "oneOf"
): any[] {
const itemsArray = items[schemaType] as SchemaObject[];
return itemsArray.map((item: SchemaObject) => {
// If items has properties, merge them with each item
if (items.properties) {
const combinedSchema = {
...item,
properties: {
...items.properties, // Common properties from parent
...item.properties, // Specific properties from this anyOf/oneOf item
},
};
// Remove anyOf/oneOf to prevent infinite recursion when calling sampleRequestFromSchema
delete combinedSchema[schemaType];
return sampleRequestFromSchema(combinedSchema);
}
return sampleRequestFromSchema(item);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,11 @@ export const sampleResponseFromSchema = (schema: SchemaObject = {}): any => {

if (type === "array") {
if (Array.isArray(items?.anyOf)) {
return items?.anyOf.map((item: any) => sampleResponseFromSchema(item));
return processArrayItems(items, "anyOf");
}

if (Array.isArray(items?.oneOf)) {
return items?.oneOf.map((item: any) => sampleResponseFromSchema(item));
return processArrayItems(items, "oneOf");
}

return [sampleResponseFromSchema(items)];
Expand Down Expand Up @@ -236,3 +236,26 @@ function normalizeArray(arr: any) {
}
return [arr];
}

function processArrayItems(
items: SchemaObject,
schemaType: "anyOf" | "oneOf"
): any[] {
const itemsArray = items[schemaType] as SchemaObject[];
return itemsArray.map((item: SchemaObject) => {
// If items has properties, merge them with each item
if (items.properties) {
const combinedSchema = {
...item,
properties: {
...items.properties, // Common properties from parent
...item.properties, // Specific properties from this anyOf/oneOf item
},
};
// Remove anyOf/oneOf to prevent infinite recursion when calling sampleResponseFromSchema
delete combinedSchema[schemaType];
return sampleResponseFromSchema(combinedSchema);
}
return sampleResponseFromSchema(item);
});
}
Loading
Loading