Skip to content
Open
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
10 changes: 9 additions & 1 deletion rest/.jvm/src/test/resources/RestTestApi.json
Original file line number Diff line number Diff line change
Expand Up @@ -805,17 +805,20 @@
"oneOf": [
{
"type": "object",
"title": "RestEntity",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, are you sure this correct ? I don't know the context of your usecase, but it creates more then one schema with the same title, might break some API generators

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the open api generator for sure works wrong for nested hierarchies, because it encodes it the same way like the flatten ones (but there is no discriminator). This solution at least works for us (maybe I miss sth else)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think something might go wrong when you add @title for RestEntity class

"properties": {
"RestEntity": {
"$ref": "#/components/schemas/RestEntity"
}
},
"additionalProperties": false,
"required": [
"RestEntity"
]
},
{
"type": "object",
"title": "RestOtherEntity",
"properties": {
"RestOtherEntity": {
"type": "object",
Expand All @@ -830,23 +833,28 @@
}
}
},
"additionalProperties": false,
"required": [
"fuu",
"kek"
]
}
},
"additionalProperties": false,
"required": [
"RestOtherEntity"
]
},
{
"type": "object",
"title": "SingletonEntity",
"properties": {
"SingletonEntity": {
"type": "object"
"type": "object",
"additionalProperties": false
}
},
"additionalProperties": false,
"required": [
"SingletonEntity"
]
Expand Down
19 changes: 14 additions & 5 deletions rest/src/main/scala/io/udash/rest/openapi/RestStructure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,20 @@ object RestStructure extends AdtMetadataCompanion[RestStructure] {
val caseSchemas = cases.map { c =>
val baseSchema = resolver.resolve(c.caseSchema(caseFieldOpt))
if (caseFieldOpt.nonEmpty) baseSchema
else RefOr(Schema(
`type` = DataType.Object,
properties = IListMap(c.info.rawName -> baseSchema),
required = List(c.info.rawName)
))
else {
val adjustedBase = baseSchema match {
case RefOr.Value(s) if s.`type`.contains(DataType.Object) && s.additionalProperties == AdditionalProperties.Flag(value = true) =>
RefOr(s.copy(additionalProperties = AdditionalProperties.Flag(value = false)))
case other => other
}
RefOr(Schema(
`type` = DataType.Object,
title = c.info.rawName,
properties = IListMap(c.info.rawName -> adjustedBase),
additionalProperties = AdditionalProperties.Flag(value = false),
required = List(c.info.rawName),
))
}
}
val disc = caseFieldOpt.map { caseFieldName =>
val mapping = IListMap((cases zip caseSchemas).collect {
Expand Down
120 changes: 120 additions & 0 deletions rest/src/test/scala/io/udash/rest/openapi/RestSchemaTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,18 @@ object HierarchyRoot {
RestStructure.materialize[HierarchyRoot[String]].standaloneSchema.named("StringHierarchy")
}

sealed trait NestedHierarchy
final case class NestedHierarchyCase(value: String) extends NestedHierarchy
final case class NestedHierarchyCase2(value: Int) extends NestedHierarchy

object NestedHierarchy extends RestDataCompanion[NestedHierarchy]

sealed trait NestedHierarchyWithEdgeCases
@transparent final case class TransparentCase(value: String) extends NestedHierarchyWithEdgeCases
final case class MapCase(entries: Map[String, Int]) extends NestedHierarchyWithEdgeCases

object NestedHierarchyWithEdgeCases extends RestDataCompanion[NestedHierarchyWithEdgeCases]

@flatten("case") sealed trait FullyQualifiedHierarchy
object FullyQualifiedHierarchy extends RestDataCompanionWithDeps[FullyQualifiedNames.type, FullyQualifiedHierarchy] {
final case class Foo(str: String) extends FullyQualifiedHierarchy
Expand Down Expand Up @@ -349,6 +361,114 @@ class RestSchemaTest extends AnyFunSuite {
|}""".stripMargin)
}

test("Nested hierarchy") {
assert(allSchemasStr[NestedHierarchy] ==
"""{
| "NestedHierarchy": {
| "type": "object",
| "oneOf": [
| {
| "type": "object",
| "title": "NestedHierarchyCase",
| "properties": {
| "NestedHierarchyCase": {
| "type": "object",
| "properties": {
| "value": {
| "type": "string"
| }
| },
| "additionalProperties": false,
| "required": [
| "value"
| ]
| }
| },
| "additionalProperties": false,
| "required": [
| "NestedHierarchyCase"
| ]
| },
| {
| "type": "object",
| "title": "NestedHierarchyCase2",
| "properties": {
| "NestedHierarchyCase2": {
| "type": "object",
| "properties": {
| "value": {
| "type": "integer",
| "format": "int32"
| }
| },
| "additionalProperties": false,
| "required": [
| "value"
| ]
| }
| },
| "additionalProperties": false,
| "required": [
| "NestedHierarchyCase2"
| ]
| }
| ]
| }
|}""".stripMargin
)
}
Comment thread
halotukozak marked this conversation as resolved.

test("Nested hierarchy with transparent and map cases") {
assert(allSchemasStr[NestedHierarchyWithEdgeCases] ==
"""{
| "NestedHierarchyWithEdgeCases": {
| "type": "object",
| "oneOf": [
| {
| "type": "object",
| "title": "TransparentCase",
| "properties": {
| "TransparentCase": {
| "type": "string"
| }
| },
| "additionalProperties": false,
| "required": [
| "TransparentCase"
| ]
| },
| {
| "type": "object",
| "title": "MapCase",
| "properties": {
| "MapCase": {
| "type": "object",
| "properties": {
| "entries": {
| "type": "object",
| "additionalProperties": {
| "type": "integer",
| "format": "int32"
| }
| }
| },
| "additionalProperties": false,
| "required": [
| "entries"
| ]
| }
| },
| "additionalProperties": false,
| "required": [
| "MapCase"
| ]
| }
| ]
| }
|}""".stripMargin
)
}

test("Customized schema name") {
assert(allSchemasStr[CustomSchemaNameHierarchy] ==
"""{
Expand Down
Loading