Skip to content

Commit

Permalink
Merge pull request #3327 from softwaremill/independent-customisation-…
Browse files Browse the repository at this point in the history
…option

Properly handle independent customisation of referenced schemas, where one is an option
  • Loading branch information
adamw authored Nov 17, 2023
2 parents 9cf1603 + e2d4ebc commit e1ea054
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ private[schema] class TSchemaToASchema(toSchemaReference: ToSchemaReference, mar
case TSchemaType.SArray(nested @ TSchema(_, Some(name), _, _, _, _, _, _, _, _, _)) =>
ASchema(SchemaType.Array).copy(items = Some(toSchemaReference.map(nested, name)))
case TSchemaType.SArray(el) => ASchema(SchemaType.Array).copy(items = Some(apply(el)))
case TSchemaType.SOption(nested @ TSchema(_, Some(name), _, _, _, _, _, _, _, _, _)) => {
val ref = toSchemaReference.map(nested, name)
if (!markOptionsAsNullable) ref
else ASchema.oneOf(List(ref, ASchema(SchemaType.Null)), None)
}
case opt @ TSchemaType.SOption(nested @ TSchema(_, Some(name), _, _, _, _, _, _, _, _, _)) =>
// #3288: in case there are multiple different customisations of the nested schema, we need to propagate the
// metadata to properly customise the reference. These are also propagated in ToKeyedSchemas when computing
// the initial list of schemas.
val propagated = propagateMetadataForOption(schema, opt).element
val ref = toSchemaReference.map(propagated, name)
if (!markOptionsAsNullable) ref else ASchema.oneOf(List(ref, ASchema(SchemaType.Null)), None)
case TSchemaType.SOption(el) => apply(el, isOptionElement = true)
case TSchemaType.SBinary() => ASchema(SchemaType.String).copy(format = SchemaFormat.Binary)
case TSchemaType.SDate() => ASchema(SchemaType.String).copy(format = SchemaFormat.Date)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
openapi: 3.1.0
info:
title: Entities
version: '1.0'
paths:
/:
get:
operationId: getRoot
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/HasCollectionDeprecated'
required: true
responses:
'200':
description: ''
'400':
description: 'Invalid value for: body'
content:
text/plain:
schema:
type: string
components:
schemas:
Data1:
required:
- x
type: object
properties:
x:
type: string
HasCollectionDeprecated:
type: object
properties:
field1:
type: array
items:
$ref: '#/components/schemas/Data1'
field2:
type: array
items:
$ref: '#/components/schemas/Data1'
deprecated: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
openapi: 3.1.0
info:
title: Entities
version: '1.0'
paths:
/:
get:
operationId: getRoot
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/HasOptionalDeprecated'
required: true
responses:
'200':
description: ''
'400':
description: 'Invalid value for: body'
content:
text/plain:
schema:
type: string
components:
schemas:
Data1:
required:
- x
type: object
properties:
x:
type: string
HasOptionalDeprecated:
required:
- field1
type: object
properties:
field1:
$ref: '#/components/schemas/Data1'
field2:
$ref: '#/components/schemas/Data1'
deprecated: true
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,32 @@ class VerifyYamlMultiCustomiseSchemaTest extends AnyFunSuite with Matchers {

actualYamlNoIndent shouldBe expectedYaml
}

test("deprecated optional reference field, when there's also a non-deprecated one") {
val expectedYaml = load("multi_customise_schema/expected_deprecated_optional_field.yml")
val actualYaml = OpenAPIDocsInterpreter()
.toOpenAPI(endpoint.in(jsonBody[HasOptionalDeprecated]), Info("Entities", "1.0"))
.toYaml

val actualYamlNoIndent = noIndentation(actualYaml)
actualYamlNoIndent shouldBe expectedYaml
}

test("deprecated optional array field, when there's also a non-deprecated one") {
val expectedYaml = load("multi_customise_schema/expected_deprecated_array_field.yml")
val actualYaml = OpenAPIDocsInterpreter()
.toOpenAPI(endpoint.in(jsonBody[HasCollectionDeprecated]), Info("Entities", "1.0"))
.toYaml

val actualYamlNoIndent = noIndentation(actualYaml)
actualYamlNoIndent shouldBe expectedYaml
}
}

object VerifyYamlMultiCustomiseSchemaTest {
case class Data1(x: String)
case class Data2(@deprecated @description("aaa") a: Data1, @description("bbb") b: Data1)

case class HasOptionalDeprecated(field1: Data1, @Schema.annotations.deprecated field2: Option[Data1])
case class HasCollectionDeprecated(field1: List[Data1], @Schema.annotations.deprecated field2: List[Data1])
}

0 comments on commit e1ea054

Please sign in to comment.