Skip to content

Commit

Permalink
Fix requestBody decoding for sbt-openapi-codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
mhertogs committed Mar 5, 2021
1 parent 7eaf121 commit 7ba7936
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 4 deletions.
Expand Up @@ -80,7 +80,8 @@ class EndpointGenerator {
.mkString("\n")

val rqBody = requestBody.fold("") { b =>
s"\n.in(${contentTypeMapper(b.contentType, b.schema, b.required)})"
if (b.content.size != 1) throw new NotImplementedError("We can handle only one requestBody content!")
s"\n.in(${contentTypeMapper(b.content.head.contentType, b.content.head.schema, b.required)})"
}

params + rqBody
Expand Down
Expand Up @@ -46,11 +46,16 @@ object OpenapiModels {

case class OpenapiRequestBody(
required: Boolean,
description: Option[String],
content: Seq[OpenapiRequestBodyContent]
)

case class OpenapiResponseContent(
contentType: String,
schema: OpenapiSchemaType
)

case class OpenapiResponseContent(
case class OpenapiRequestBodyContent(
contentType: String,
schema: OpenapiSchemaType
)
Expand Down Expand Up @@ -96,9 +101,42 @@ object OpenapiModels {
}
}

implicit val OpenapiRequestBodyContentDecoder: Decoder[Seq[OpenapiRequestBodyContent]] = { (c: HCursor) =>
case class Holder(d: OpenapiSchemaType)
implicit val InnerDecoder: Decoder[Holder] = { (c: HCursor) =>
for {
schema <- c.downField("schema").as[OpenapiSchemaType]
} yield {
Holder(schema)
}
}
for {
responses <- c.as[Map[String, Holder]]
} yield {
responses.map { case (ct, s) => OpenapiRequestBodyContent(ct, s.d) }.toSeq
}
}

implicit val OpenapiRequestBodyDecoder: Decoder[OpenapiRequestBody] = { (c: HCursor) =>
implicit val InnerDecoder: Decoder[(String, Seq[OpenapiRequestBodyContent])] = { (c: HCursor) =>
for {
description <- c.downField("description").as[String]
content <- c.downField("content").as[Seq[OpenapiRequestBodyContent]]
} yield {
(description, content)
}
}
for {
requiredOpt <- c.downField("required").as[Option[Boolean]]
description <- c.downField("description").as[Option[String]]
content <- c.downField("content").as[Seq[OpenapiRequestBodyContent]]
} yield {
OpenapiRequestBody(required = requiredOpt.getOrElse(false), description, content)
}
}

implicit val OpenapiInfoDecoder: Decoder[OpenapiInfo] = deriveDecoder[OpenapiInfo]
implicit val OpenapiParameterDecoder: Decoder[OpenapiParameter] = deriveDecoder[OpenapiParameter]
implicit val OpenapiRequestBodyDecoder: Decoder[OpenapiRequestBody] = deriveDecoder[OpenapiRequestBody]
implicit val OpenapiPathMethodDecoder: Decoder[Seq[OpenapiPathMethod]] = { (c: HCursor) =>
implicit val InnerDecoder: Decoder[(Seq[OpenapiParameter], Seq[OpenapiResponse], Option[OpenapiRequestBody], Option[String])] = {
(c: HCursor) =>
Expand Down
74 changes: 73 additions & 1 deletion sbt/sbt-openapi-codegen/src/test/scala/codegen/TestHelpers.scala
@@ -1,17 +1,20 @@
package codegen

import codegen.openapi.models.OpenapiComponent
import codegen.openapi.models.{OpenapiComponent, OpenapiSchemaType}
import codegen.openapi.models.OpenapiModels.{
OpenapiDocument,
OpenapiInfo,
OpenapiParameter,
OpenapiPath,
OpenapiPathMethod,
OpenapiRequestBody,
OpenapiRequestBodyContent,
OpenapiResponse,
OpenapiResponseContent
}
import codegen.openapi.models.OpenapiSchemaType.{
OpenapiSchemaArray,
OpenapiSchemaDouble,
OpenapiSchemaInt,
OpenapiSchemaObject,
OpenapiSchemaRef,
Expand All @@ -28,6 +31,46 @@ object TestHelpers {
| version: '1.0'
|paths:
| /books/{genre}/{year}:
| post:
| operationId: postBooksGenreYear
| parameters:
| - name: genre
| in: path
| required: true
| schema:
| type: string
| - name: year
| in: path
| required: true
| schema:
| type: integer
| - name: limit
| in: query
| description: Maximum number of books to retrieve
| required: true
| schema:
| type: integer
| - name: X-Auth-Token
| in: header
| required: true
| schema:
| type: string
| requestBody:
| description: Book to add
| required: true
| content:
| application/json:
| schema:
| $ref: '#/components/schemas/Book'
| responses:
| '200':
| description: ''
| content:
| application/json:
| schema:
| type: array
| items:
| $ref: '#/components/schemas/Book'
| get:
| operationId: getBooksGenreYear
| parameters:
Expand Down Expand Up @@ -85,6 +128,35 @@ object TestHelpers {
OpenapiPath(
"/books/{genre}/{year}",
Seq(
OpenapiPathMethod(
"post",
Seq(
OpenapiParameter("genre", "path", true, None, OpenapiSchemaString(false)),
OpenapiParameter("year", "path", true, None, OpenapiSchemaInt(false)),
OpenapiParameter("limit", "query", true, Some("Maximum number of books to retrieve"), OpenapiSchemaInt(false)),
OpenapiParameter("X-Auth-Token", "header", true, None, OpenapiSchemaString(false))
),
Seq(
OpenapiResponse(
"200",
"",
Seq(OpenapiResponseContent("application/json", OpenapiSchemaArray(OpenapiSchemaRef("#/components/schemas/Book"), false)))
)
),
Option(
OpenapiRequestBody(
required = true,
content = Seq(
OpenapiRequestBodyContent(
"application/json",
OpenapiSchemaRef("#/components/schemas/Book")
)
),
description = Some("Book to add")
)
),
None
),
OpenapiPathMethod(
"get",
Seq(
Expand Down

0 comments on commit 7ba7936

Please sign in to comment.