updates for response class to 1.2 spec

This commit is contained in:
Tony Tam 2013-08-11 15:36:16 -07:00
parent 93067a0ce0
commit aa1fbb680b
6 changed files with 239 additions and 171 deletions

View File

@ -27,6 +27,47 @@ object SwaggerSerializers {
("array", "") -> "Array"
)
def toJsonSchema(name: String, `type`: String): JObject = {
`type` match {
case "int" => (name -> "integer") ~ ("format" -> "int32")
case "long" => (name -> "integer") ~ ("format" -> "int64")
case "float" => (name -> "number") ~ ("format" -> "float")
case "double" => (name -> "number") ~ ("format" -> "double")
case "string" => (name -> "string") ~ ("format" -> JNothing)
case "byte" => (name -> "string") ~ ("format" -> "byte")
case "boolean" => (name -> "boolean") ~ ("format" -> JNothing)
case "Date" => (name -> "string") ~ ("format" -> "date-time")
case "date" => (name -> "string") ~ ("format" -> "date")
case "date-time" => (name -> "string") ~ ("format" -> "date-time")
case _ => {
val ComplexTypeMatcher = "([a-zA-Z]*)\\[([a-zA-Z\\.\\-]*)\\].*".r
`type` match {
case ComplexTypeMatcher(container, value) =>
toJsonSchemaContainer(container) ~ {
("items" -> {if(isSimpleType(value))
toJsonSchema("type", value)
else
toJsonSchema("$ref", value)})
}
case _ => (name -> `type`) ~ ("format" -> JNothing)
}
}
}
}
def toJsonSchemaContainer(name: String): JObject = {
name match {
case "List" => ("type" -> "array") ~ ("format" -> JNothing)
case "Array" => ("type" -> "array") ~ ("format" -> JNothing)
case "Set" => ("type" -> "array") ~ ("uniqueItems" -> true)
case _ => ("type" -> JNothing)
}
}
def isSimpleType(name: String) = {
Set("int", "long", "float", "double", "string", "byte", "boolean", "Date", "date", "date-time", "array").contains(name)
}
def formats(version: String) = {
version match {
case "1.1" => LegacySerializers.formats
@ -205,6 +246,21 @@ object SwaggerSerializers {
case json =>
implicit val fmts: Formats = formats
val responseClass = (json \ "items") match {
case e: JObject => {
val inner = {
(e \ "type").extractOrElse({
(e \ "$ref").extract[String]
})
}
"%s[%s]".format((json \ "type").extract[String], inner)
}
case _ => (json \ "type").extractOrElse({
!!(json, OPERATION, "responseClass", "missing required field", ERROR)
""
})
}
Operation(
(json \ "httpMethod").extractOrElse(
(json \ "method").extractOrElse({
@ -214,10 +270,7 @@ object SwaggerSerializers {
),
(json \ "summary").extract[String],
(json \ "notes").extractOrElse(""),
(json \ "responseClass").extractOrElse({
!!(json, OPERATION, "responseClass", "missing required field", ERROR)
""
}),
responseClass,
(json \ "nickname").extractOrElse({
!!(json, OPERATION, "nickname", "missing required field", ERROR)
""
@ -233,11 +286,24 @@ object SwaggerSerializers {
)
}, {
case x: Operation =>
val ComplexTypeMatcher = "([a-zA-Z]*)\\[([a-zA-Z\\.\\-]*)\\].*".r
val output = x.responseClass match {
case ComplexTypeMatcher(container, value) =>
toJsonSchemaContainer(container) ~ {
("items" -> {if(isSimpleType(value))
toJsonSchema("type", value)
else
toJsonSchema("$ref", value)})
}
case _ => toJsonSchema("type", x.responseClass) ~ ("format" -> JNothing)
}
implicit val fmts = formats
("method" -> x.method) ~
("summary" -> x.summary) ~
("notes" -> x.notes) ~
("responseClass" -> x.responseClass) ~
output ~
("nickname" -> x.nickname) ~
("parameters" -> Extraction.decompose(x.parameters)) ~
("responseMessages" -> {

View File

@ -12,13 +12,12 @@
"apis": [
{
"path": "/pet/{petId}",
"description":"Operations about pets",
"operations": [
{
"method": "GET",
"summary": "Find pet by ID",
"notes": "Returns a pet based on ID",
"responseClass": "Pet",
"type": "Pet",
"nickname": "getPetById",
"produces": [
"application/json",
@ -52,7 +51,7 @@
"method": "DELETE",
"summary": "Deletes a pet",
"notes": "",
"responseClass": "void",
"type": "void",
"nickname": "deletePet",
"parameters": [
{
@ -76,11 +75,34 @@
{
"path": "/pet",
"operations": [
{
"method": "POST",
"summary": "Add a new pet to the store",
"notes": "",
"type": "void",
"nickname": "addPet",
"parameters": [
{
"name": "body",
"description": "Pet object that needs to be added to the store",
"required": true,
"allowMultiple": false,
"type": "Pet",
"paramType": "body"
}
],
"responseMessages": [
{
"code": 405,
"message": "Invalid input"
}
]
},
{
"method": "PUT",
"summary": "Update an existing pet",
"notes": "",
"responseClass": "void",
"type": "void",
"nickname": "updatePet",
"parameters": [
{
@ -106,29 +128,6 @@
"message": "Validation exception"
}
]
},
{
"method": "POST",
"summary": "Add a new pet to the store",
"notes": "",
"responseClass": "void",
"nickname": "addPet",
"parameters": [
{
"name": "body",
"description": "Pet object that needs to be added to the store",
"required": true,
"allowMultiple": false,
"type": "Pet",
"paramType": "body"
}
],
"responseMessages": [
{
"code": 405,
"message": "Invalid input"
}
]
}
]
},
@ -139,7 +138,10 @@
"method": "GET",
"summary": "Finds Pets by status",
"notes": "Multiple status values can be provided with comma seperated strings",
"responseClass": "List[Pet]",
"type": "array",
"items": {
"$ref": "Pet"
},
"nickname": "findPetsByStatus",
"produces": [
"application/json",
@ -177,7 +179,10 @@
"method": "GET",
"summary": "Finds Pets by tags",
"notes": "Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.",
"responseClass": "List[Pet]",
"type": "array",
"items": {
"$ref": "Pet"
},
"nickname": "findPetsByTags",
"produces": [
"application/json",
@ -221,10 +226,14 @@
"id": "Pet",
"description": "A pet is a person's best friend",
"required": [
"name",
"id"
"id",
"name"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"tags": {
"type": "array",
"items": {
@ -234,10 +243,6 @@
"name": {
"type": "string"
},
"id": {
"type": "integer",
"format": "int64"
},
"status": {
"type": "string",
"description": "pet status in the store",

View File

@ -15,7 +15,7 @@
"method": "GET",
"summary": "Find purchase order by ID",
"notes": "For valid response try integer IDs with value <= 5. Anything above 5 or nonintegers will generate API errors",
"responseClass": "Order",
"type": "Order",
"nickname": "getOrderById",
"produces": [
"application/json",
@ -46,7 +46,7 @@
"method": "DELETE",
"summary": "Delete purchase order by ID",
"notes": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors",
"responseClass": "void",
"type": "void",
"nickname": "deleteOrder",
"parameters": [
{
@ -78,7 +78,7 @@
"method": "POST",
"summary": "Place an order for a pet",
"notes": "",
"responseClass": "void",
"type": "void",
"nickname": "placeOrder",
"parameters": [
{
@ -104,6 +104,10 @@
"Order": {
"id": "Order",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"status": {
"type": "string",
"description": "Order Status",
@ -113,14 +117,6 @@
"delivered"
]
},
"id": {
"type": "integer",
"format": "int64"
},
"shipDate": {
"type": "string",
"format": "date-time"
},
"petId": {
"type": "integer",
"format": "int64"
@ -128,6 +124,10 @@
"quantity": {
"type": "integer",
"format": "int32"
},
"shipDate": {
"type": "string",
"format": "date-time"
}
}
}

View File

@ -9,44 +9,85 @@
],
"apis": [
{
"path": "/user/{username}",
"path": "/user",
"operations": [
{
"method": "GET",
"summary": "Get user by user name",
"notes": "",
"responseClass": "User",
"nickname": "getUserByName",
"produces": [
"application/json",
"application/xml"
],
"method": "POST",
"summary": "Create user",
"notes": "This can only be done by the logged in user.",
"type": "void",
"nickname": "createUser",
"parameters": [
{
"name": "username",
"description": "The name that needs to be fetched. Use user1 for testing.",
"name": "body",
"description": "Created user object",
"required": true,
"allowMultiple": false,
"type": "string",
"paramType": "path"
}
],
"responseMessages": [
{
"code": 400,
"message": "Invalid username supplied"
},
{
"code": 404,
"message": "User not found"
"type": "User",
"paramType": "body"
}
]
},
}
]
},
{
"path": "/user/createWithArray",
"operations": [
{
"method": "POST",
"summary": "Creates list of users with given input array",
"notes": "",
"type": "void",
"nickname": "createUsersWithArrayInput",
"parameters": [
{
"name": "body",
"description": "List of user object",
"required": true,
"allowMultiple": false,
"type": "array",
"items": {
"$ref": "User"
},
"paramType": "body"
}
]
}
]
},
{
"path": "/user/createWithList",
"operations": [
{
"method": "POST",
"summary": "Creates list of users with given list input",
"notes": "",
"type": "void",
"nickname": "createUsersWithListInput",
"parameters": [
{
"name": "body",
"description": "List of user object",
"required": true,
"allowMultiple": false,
"type": "array",
"items": {
"$ref": "User"
},
"paramType": "body"
}
]
}
]
},
{
"path": "/user/{username}",
"operations": [
{
"method": "PUT",
"summary": "Updated user",
"notes": "This can only be done by the logged in user.",
"responseClass": "void",
"type": "void",
"nickname": "updateUser",
"parameters": [
{
@ -81,7 +122,7 @@
"method": "DELETE",
"summary": "Delete user",
"notes": "This can only be done by the logged in user.",
"responseClass": "void",
"type": "void",
"nickname": "deleteUser",
"parameters": [
{
@ -103,6 +144,37 @@
"message": "User not found"
}
]
},
{
"method": "GET",
"summary": "Get user by user name",
"notes": "",
"type": "User",
"nickname": "getUserByName",
"produces": [
"application/json",
"application/xml"
],
"parameters": [
{
"name": "username",
"description": "The name that needs to be fetched. Use user1 for testing.",
"required": true,
"allowMultiple": false,
"type": "string",
"paramType": "path"
}
],
"responseMessages": [
{
"code": 400,
"message": "Invalid username supplied"
},
{
"code": 404,
"message": "User not found"
}
]
}
]
},
@ -113,7 +185,7 @@
"method": "GET",
"summary": "Logs user into the system",
"notes": "",
"responseClass": "string",
"type": "string",
"nickname": "loginUser",
"produces": [
"text/plain"
@ -152,7 +224,7 @@
"method": "GET",
"summary": "Logs out current logged in user session",
"notes": "",
"responseClass": "void",
"type": "void",
"nickname": "logoutUser",
"produces": [
"text/plain"
@ -160,84 +232,16 @@
"parameters": []
}
]
},
{
"path": "/user",
"operations": [
{
"method": "POST",
"summary": "Create user",
"notes": "This can only be done by the logged in user.",
"responseClass": "void",
"nickname": "createUser",
"parameters": [
{
"name": "body",
"description": "Created user object",
"required": true,
"allowMultiple": false,
"type": "User",
"paramType": "body"
}
]
}
]
},
{
"path": "/user/createWithArray",
"operations": [
{
"method": "POST",
"summary": "Creates list of users with given input array",
"notes": "",
"responseClass": "void",
"nickname": "createUsersWithArrayInput",
"parameters": [
{
"name": "body",
"description": "List of user object",
"required": true,
"allowMultiple": false,
"type": "array",
"items": {
"$ref": "User"
},
"paramType": "body"
}
]
}
]
},
{
"path": "/user/createWithList",
"operations": [
{
"method": "POST",
"summary": "Creates list of users with given list input",
"notes": "",
"responseClass": "void",
"nickname": "createUsersWithListInput",
"parameters": [
{
"name": "body",
"description": "List of user object",
"required": true,
"allowMultiple": false,
"type": "array",
"items": {
"$ref": "User"
},
"paramType": "body"
}
]
}
]
}
],
"models": {
"User": {
"id": "User",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"username": {
"type": "string"
},
@ -247,9 +251,8 @@
"email": {
"type": "string"
},
"id": {
"type": "integer",
"format": "int64"
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
@ -266,9 +269,6 @@
"2-active",
"3-closed"
]
},
"firstName": {
"type": "string"
}
}
}

View File

@ -145,7 +145,7 @@ class OperationValidationTest extends FlatSpec with ShouldMatchers {
"httpMethod":"GET",
"summary":"the summary",
"notes":"the notes",
"responseClass":"string",
"type":"string",
"nickname":"getMeSomeStrings",
"parameters":[
{
@ -183,7 +183,7 @@ class OperationValidationTest extends FlatSpec with ShouldMatchers {
List.empty,
List(Parameter("id", Some("the id"), Some("-1"), false, true, "string", AllowableListValues(List("a","b","c")), "query"))
)
write(op) should be ("""{"method":"get","summary":"the summary","notes":"the notes","responseClass":"string","nickname":"getMeSomeStrings","parameters":[{"name":"id","description":"the id","defaultValue":"-1","required":false,"allowMultiple":true,"type":"string","allowableValues":{"valueType":"LIST","values":["a","b","c"]},"paramType":"query"}]}""")
write(op) should be ("""{"method":"get","summary":"the summary","notes":"the notes","type":"string","nickname":"getMeSomeStrings","parameters":[{"name":"id","description":"the id","defaultValue":"-1","required":false,"allowMultiple":true,"type":"string","allowableValues":{"valueType":"LIST","values":["a","b","c"]},"paramType":"query"}]}""")
}
}
@ -225,13 +225,10 @@ class ParameterValidationTest extends FlatSpec with ShouldMatchers {
"defaultValue":"false",
"description":"Show duplicate examples from different sources",
"required":"false",
"allowableValues":{
"values":[
false,
true
],
"valueType":"LIST"
},
"enum":[
false,
true
],
"type":"string",
"allowMultiple":false,
"paramType":"query"

View File

@ -138,7 +138,7 @@ class ApiDescriptionSerializersTest extends FlatSpec with ShouldMatchers {
"method":"GET",
"summary":"the summary",
"notes":"the notes",
"responseClass":"string",
"type":"string",
"nickname":"getMeSomeStrings",
"parameters":[
{
@ -203,7 +203,7 @@ class ApiDescriptionSerializersTest extends FlatSpec with ShouldMatchers {
List(Parameter("id", Some("the id"), Some("-1"), false, true, "string", AllowableListValues(List("a","b","c")), "query"))
))
)
write(l) should be ("""{"path":"/foo/bar","description":"the description","operations":[{"method":"get","summary":"the summary","notes":"the notes","responseClass":"string","nickname":"getMeSomeStrings","parameters":[{"name":"id","description":"the id","defaultValue":"-1","required":false,"allowMultiple":true,"type":"string","allowableValues":{"valueType":"LIST","values":["a","b","c"]},"paramType":"query"}]}]}""")
write(l) should be ("""{"path":"/foo/bar","description":"the description","operations":[{"method":"get","summary":"the summary","notes":"the notes","type":"string","nickname":"getMeSomeStrings","parameters":[{"name":"id","description":"the id","defaultValue":"-1","required":false,"allowMultiple":true,"type":"string","allowableValues":{"valueType":"LIST","values":["a","b","c"]},"paramType":"query"}]}]}""")
}
}
@ -217,7 +217,7 @@ class OperationSerializersTest extends FlatSpec with ShouldMatchers {
"method":"GET",
"summary":"the summary",
"notes":"the notes",
"responseClass":"string",
"type":"string",
"nickname":"getMeSomeStrings",
"parameters":[
{
@ -271,7 +271,7 @@ class OperationSerializersTest extends FlatSpec with ShouldMatchers {
List.empty,
List(Parameter("id", Some("the id"), Some("-1"), false, true, "string", AllowableListValues(List("a","b","c")), "query"))
)
write(op) should be ("""{"method":"get","summary":"the summary","notes":"the notes","responseClass":"string","nickname":"getMeSomeStrings","parameters":[{"name":"id","description":"the id","defaultValue":"-1","required":false,"allowMultiple":true,"type":"string","allowableValues":{"valueType":"LIST","values":["a","b","c"]},"paramType":"query"}]}""")
write(op) should be ("""{"method":"get","summary":"the summary","notes":"the notes","type":"string","nickname":"getMeSomeStrings","parameters":[{"name":"id","description":"the id","defaultValue":"-1","required":false,"allowMultiple":true,"type":"string","allowableValues":{"valueType":"LIST","values":["a","b","c"]},"paramType":"query"}]}""")
}
}