Skip to content

Commit

Permalink
Merge pull request #489 from iheartradio/javakky/top-in-ref
Browse files Browse the repository at this point in the history
feat: Mix in top-level $ref
  • Loading branch information
Javakky-pxv authored Jul 28, 2022
2 parents cf923ca + ec3dfd4 commit 10a0f36
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 11 deletions.
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,8 @@ POST /tracks controller.Api.createTrack()

By placing a json or YAML file in `conf/${dir}/${file}` and referencing it with `$ref` in a comment, the file can be generated embedded in swagger.json.

⚠️ **Warning**: If a file that does not exist in `/conf` is specified, or if a typo is used for the filename, `$ref:"${filename}"` will be output as is.

example `conf/routes` file.

```
Expand All @@ -450,7 +452,7 @@ GET / controllers.HomeController.index
example `conf/swagger/home_200.yml` file.

```yaml
description: success
description: "success"
```
Of course, writing `schema` etc. will also be embedded.
Expand Down Expand Up @@ -483,6 +485,27 @@ See the following document for information on how to refer to other files by "$r

https://swagger.io/docs/specification/using-ref/

##### You can also cut out the entire comment.

This feature is very useful, but OpenAPI does not allow top-level `$ref`, so failing to embed it may result in an invalid `swagger.json`!

```
###
# $ref: './swagger/home.yml'
###
GET / controllers.HomeController.index
```
example `home.yml` file.
```yaml
summary: Top Page
responses:
200:
description: "success"
```


#### Is play java supported?

you can generate models definition from java POJO by setting the flag:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.iheart.playSwagger.OutputTransformer.SimpleOutputTransformer
import com.iheart.playSwagger.ResourceReader.read
import com.iheart.playSwagger.SwaggerParameterMapper.mapParam
import org.yaml.snakeyaml.Yaml
import play.api.libs.json.JsValue.jsValueToJsLookup
import play.api.libs.json._
import play.routes.compiler._

Expand Down Expand Up @@ -446,7 +447,9 @@ final case class SwaggerSpecGenerator(
private def endPointSpec(route: Route, tag: Option[String]) = {

def tryParseYaml(comment: String): Option[JsObject] = {
val pattern = "^\\w+:".r
// The purpose here is more to ensure that it is not in other formats such as JSON
// If invalid YAML is passed, org.yaml.snakeyaml.parser.ParserException
val pattern = "^\\w+|\\$ref:".r
pattern.findFirstIn(comment).map(_ parseYaml[JsObject](comment))
}

Expand All @@ -456,6 +459,14 @@ final case class SwaggerSpecGenerator(
else None
}

def amendBodyParam(params: JsArray): JsArray = {
val bodyParam = findByName(params, "body")
bodyParam.fold(params) { param
val enhancedBodyParam = Json.obj("in" JsString("body")) ++ param
JsArray(enhancedBodyParam +: params.value.filterNot(_ == bodyParam.get))
}
}

val paramsFromController = {
val pathParams = route.path.parts.collect {
case d: DynamicPart d.name
Expand All @@ -479,14 +490,6 @@ final case class SwaggerSpecGenerator(
})
}

def amendBodyParam(params: JsArray): JsArray = {
val bodyParam = findByName(params, "body")
bodyParam.fold(params) { param
val enhancedBodyParam = Json.obj("in" JsString("body")) ++ param
JsArray(enhancedBodyParam +: params.value.filterNot(_ == bodyParam.get))
}
}

val jsonFromComment = {
import SwaggerSpecGenerator.marker

Expand Down
8 changes: 7 additions & 1 deletion core/src/test/resources/subjects.routes
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,10 @@
# 200:
# $ref: './swagger/subject_dow_200.yml'
###
GET /dow/:subject controllers.Subjects.dayOfWeek(subject: com.iheart.playSwagger.Subject)
GET /dow/:subject controllers.Subjects.dayOfWeek(subject: com.iheart.playSwagger.Subject)

###
# $ref: './swagger/subject_dow_not.yml'
# description: 'What day of the week is that subject?'
###
GET /dow/not/:subject controllers.Subjects.hasNotDayOfWeek(subject: com.iheart.playSwagger.Subject)
13 changes: 13 additions & 0 deletions core/src/test/resources/swagger/subject_dow_not.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
responses:
200:
description: "success"
content:
application/json:
schema:
$ref: '#/definitions/com.iheart.playSwagger.DayOfWeek'
example:
success:
value:
name: "MonDay"
400:
description: "error"
Original file line number Diff line number Diff line change
Expand Up @@ -498,10 +498,12 @@ class SwaggerSpecGeneratorIntegrationSpec extends Specification {

"parse mixin referenced external file" >> {
lazy val subjectJson = (pathJson \ "/api/subjects/dow/{subject}" \ "get").as[JsObject]

"parse param" >> {
val properties = (definitionsJson \ "com.iheart.playSwagger.Subject" \ "properties").as[JsObject]
(properties \ "name" \ "type").as[String] === "string"
}

"embedding mixed responses" >> {
"description" >> {
(subjectJson \ "responses" \ "200" \ "description").as[String] === "success"
Expand All @@ -513,6 +515,24 @@ class SwaggerSpecGeneratorIntegrationSpec extends Specification {
}
}

"Top-level $ref is also embedded" >> {
lazy val subjectNotJson = (pathJson \ "/api/subjects/dow/not/{subject}" \ "get").as[JsObject]

"Information written in comments is mixed with external files" >> {
(subjectNotJson \ "description").as[String] === "What day of the week is that subject?"
}
"description_200" >> {
(subjectNotJson \ "responses" \ "200" \ "description").as[String] === "success"
}
"description_400" >> {
(subjectNotJson \ "responses" \ "400" \ "description").as[String] === "error"
}
"reference schema" >> {
(subjectNotJson \ "responses" \ "200" \ "content" \ "application/json" \ "schema" \ "$ref").as[String] ===
"#/definitions/com.iheart.playSwagger.DayOfWeek"
}
}

"should contain schemas in responses" >> {
(postBodyJson \ "responses" \ "200" \ "schema" \ "$ref").asOpt[String] === Some(
"#/definitions/com.iheart.playSwagger.FooWithSeq2"
Expand Down

0 comments on commit 10a0f36

Please sign in to comment.