diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/openapi/BigModel.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/openapi/BigModel.scala new file mode 100644 index 0000000000..9250bb416d --- /dev/null +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/openapi/BigModel.scala @@ -0,0 +1,33 @@ +package zio.http.endpoint.openapi + +import zio.schema.{DeriveSchema, Schema} + +// case class with 22+ (23 in this case) fields +final case class BigModel( + f1: Boolean, + f2: Boolean, + f3: Boolean, + f4: Boolean, + f5: Boolean, + f6: Boolean, + f7: Boolean, + f8: Boolean, + f9: Boolean, + f10: Boolean, + f11: Boolean, + f12: Boolean, + f13: Boolean, + f14: Boolean, + f15: Boolean, + f16: Boolean, + f17: Boolean, + f18: Boolean, + f19: Boolean, + f20: Boolean, + f21: Boolean, + f22: Boolean, + f23: Boolean, +) +object BigModel { + implicit val codec: Schema[BigModel] = DeriveSchema.gen[BigModel] +} diff --git a/zio-http/jvm/src/test/scala/zio/http/endpoint/openapi/OpenAPIGenSpec.scala b/zio-http/jvm/src/test/scala/zio/http/endpoint/openapi/OpenAPIGenSpec.scala index 8a1057002b..99faac7f3d 100644 --- a/zio-http/jvm/src/test/scala/zio/http/endpoint/openapi/OpenAPIGenSpec.scala +++ b/zio-http/jvm/src/test/scala/zio/http/endpoint/openapi/OpenAPIGenSpec.scala @@ -3101,6 +3101,142 @@ object OpenAPIGenSpec extends ZIOSpecDefault { |}""".stripMargin assertTrue(json == toJsonAst(expectedJson)) }, + test("components are generated for big model with 22+ fields") { + val endpoint = Endpoint(Method.GET / "api" / "v1" / "users").out[BigModel] + val generated = OpenAPIGen.fromEndpoints(endpoint) + val json = toJsonAst(generated) + val expectedJson = """{ + | "openapi" : "3.1.0", + | "info" : { + | "title" : "", + | "version" : "" + | }, + | "paths" : { + | "/api/v1/users" : { + | "get" : { + | "responses" : { + | "200" : { + | "content" : { + | "application/json" : { + | "schema" : { + | "$ref" : "#/components/schemas/BigModel" + | } + | } + | } + | } + | } + | } + | } + | }, + | "components" : { + | "schemas" : { + | "BigModel" : { + | "type" : "object", + | "properties" : { + | "f20" : { + | "type" : "boolean" + | }, + | "f19" : { + | "type" : "boolean" + | }, + | "f7" : { + | "type" : "boolean" + | }, + | "f6" : { + | "type" : "boolean" + | }, + | "f14" : { + | "type" : "boolean" + | }, + | "f18" : { + | "type" : "boolean" + | }, + | "f8" : { + | "type" : "boolean" + | }, + | "f10" : { + | "type" : "boolean" + | }, + | "f5" : { + | "type" : "boolean" + | }, + | "f21" : { + | "type" : "boolean" + | }, + | "f3" : { + | "type" : "boolean" + | }, + | "f9" : { + | "type" : "boolean" + | }, + | "f17" : { + | "type" : "boolean" + | }, + | "f22" : { + | "type" : "boolean" + | }, + | "f15" : { + | "type" : "boolean" + | }, + | "f16" : { + | "type" : "boolean" + | }, + | "f1" : { + | "type" : "boolean" + | }, + | "f13" : { + | "type" : "boolean" + | }, + | "f4" : { + | "type" : "boolean" + | }, + | "f11" : { + | "type" : "boolean" + | }, + | "f23" : { + | "type" : "boolean" + | }, + | "f2" : { + | "type" : "boolean" + | }, + | "f12" : { + | "type" : "boolean" + | } + | }, + | "required" : [ + | "f1", + | "f2", + | "f3", + | "f4", + | "f5", + | "f6", + | "f7", + | "f8", + | "f9", + | "f10", + | "f11", + | "f12", + | "f13", + | "f14", + | "f15", + | "f16", + | "f17", + | "f18", + | "f19", + | "f20", + | "f21", + | "f22", + | "f23" + | ] + | } + | } + | } + |} + |""".stripMargin + assertTrue( + json == toJsonAst(expectedJson), + ) + }, ) } diff --git a/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/OpenAPIGen.scala b/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/OpenAPIGen.scala index 66d4eb886d..12290210c5 100644 --- a/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/OpenAPIGen.scala +++ b/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/OpenAPIGen.scala @@ -2,6 +2,7 @@ package zio.http.endpoint.openapi import java.util.UUID +import scala.annotation.tailrec import scala.collection.immutable.ListMap import scala.collection.{immutable, mutable} @@ -9,7 +10,7 @@ import zio._ import zio.json.EncoderOps import zio.json.ast.Json -import zio.schema.Schema.Record +import zio.schema.Schema.{Record, Transform} import zio.schema.codec.JsonCodec import zio.schema.{Schema, TypeId} @@ -935,6 +936,7 @@ object OpenAPIGen { } } + @tailrec def nominal(schema: Schema[_], referenceType: SchemaStyle): Option[String] = schema match { case enumSchema: Schema.Enum[_] => @@ -955,6 +957,8 @@ object OpenAPIGen { case nominal: TypeId.Nominal => Some(nominal.fullyQualified.replace(".", "_")) } + case t: Transform[_, _, _] => + nominal(t.schema, referenceType) case _ => None }