Share
Let me write your Networking Code
Let me write your networking code
=====
When writing networking code, you want to make sure the code between the client and server implementation is consistent. After spending hours defining the APIs with your backend engineers, you’ll probably need to spend even more time implementing those details over to your code (and guess what… your backend engineers will be doing the same!). This process is boring, time consuming, and prone to errors.
Wouldn’t it be cool if this process were automated? If you could have classes and interfaces that mirror your API definition? And if they were automatically tested and ready to use out of the box?
It can be done! At Yelp, we define our APIs using Swagger Specs and we successfully automated the generation of our networking code for both servers and clients (iOS & Android). On Android, we generate Kotlin Data Classes and Retrofit APIs that mirror our spec files and are ready to use for all engineers. In this talk, we will explore how we set up our code generation pipeline and how you can start doing it, too.
Nicola Corti
Transcript
143 slides
-
LET ME WRITE YOUR NETWORKING CODE Nicola Corti Android Infra
Engineer @cortinico Community Lover (GDG Pisa - Kotlin Hamburg) ! ✈ -
Open API The Specification Swagger The Tooling Define the API
in a JSON/YAML files Build infrastructure around them SWAGGER Swagger & Open API -
!!--- swagger: '2.0' info: description: 'This is a sample server
Petstore server' -
!!--- swagger: '2.0' info: description: 'This is a sample server
Petstore server' version: 1.0.0 -
!!--- swagger: '2.0' info: description: 'This is a sample server
Petstore server' version: 1.0.0 title: Swagger Petstore -
!!--- swagger: '2.0' info: description: 'This is a sample server
Petstore server' version: 1.0.0 title: Swagger Petstore contact: email: [email protected] -
!!--- swagger: '2.0' info: description: 'This is a sample server
Petstore server' version: 1.0.0 title: Swagger Petstore contact: email: [email protected] license: name: Apache 2.0 url: http:!//!!www.apache.org/licenses/LICENSE-2.0.html -
!!--- swagger: '2.0' info: description: 'This is a sample server
Petstore server' version: 1.0.0 title: Swagger Petstore contact: email: [email protected] license: name: Apache 2.0 url: http:!//!!www.apache.org/licenses/LICENSE-2.0.html host: petstore.swagger.io -
!!--- swagger: '2.0' info: description: 'This is a sample server
Petstore server' version: 1.0.0 title: Swagger Petstore contact: email: [email protected] license: name: Apache 2.0 url: http:!//!!www.apache.org/licenses/LICENSE-2.0.html host: petstore.swagger.io basePath: "/v2" -
!!--- swagger: '2.0' info: description: 'This is a sample server
Petstore server' version: 1.0.0 title: Swagger Petstore contact: email: [email protected] license: name: Apache 2.0 url: http:!//!!www.apache.org/licenses/LICENSE-2.0.html host: petstore.swagger.io basePath: "/v2" schemes: - https - http -
basePath: “/v2" schemes: - https - http definitions: Pet: type:
object properties: -
basePath: “/v2" schemes: - https - http definitions: Pet: type:
object properties: id: type: integer format: int64 -
basePath: “/v2" schemes: - https - http definitions: Pet: type:
object properties: id: type: integer format: int64 name: type: string -
basePath: “/v2" schemes: - https - http definitions: Pet: type:
object properties: id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string -
definitions: Pet: type: object required: - name - photoUrls properties:
id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string -
properties: id: type: integer format: int64 name: type: string photoUrls:
type: array items: type: string status: type: string -
properties: id: type: integer format: int64 name: type: string photoUrls:
type: array items: type: string status: type: string description: pet status in the store -
properties: id: type: integer format: int64 name: type: string photoUrls:
type: array items: type: string status: type: string description: pet status in the store enum: - available - sold -
properties: id: type: integer format: int64 name: type: string photoUrls:
type: array items: type: string status: type: string description: pet status in the store enum: - available - sold category: -
properties: id: type: integer format: int64 name: type: string photoUrls:
type: array items: type: string status: type: string description: pet status in the store enum: - available - sold category: $ref: “#/definitions/Category" -
definitions: Pet: type: object required: - name - photoUrls properties:
id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string description: pet status in the store enum: - available - sold category: $ref: “#/definitions/Category" -
definitions: Pet: type: object required: - name - photoUrls properties:
id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string description: pet status in the store enum: - available - sold category: $ref: “#/definitions/Category" Category: -
definitions: Pet: type: object required: - name - photoUrls properties:
id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string description: pet status in the store enum: - available - sold category: $ref: “#/definitions/Category" Category: type: object -
definitions: Pet: type: object required: - name - photoUrls properties:
id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string description: pet status in the store enum: - available - sold category: $ref: “#/definitions/Category" Category: type: object properties: id: type: integer format: int64 -
definitions: Pet: type: object required: - name - photoUrls properties:
id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string description: pet status in the store enum: - available - sold category: $ref: “#/definitions/Category" Category: type: object properties: id: type: integer format: int64 name: type: string -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: - name: petId -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 -
- name: petId in: path description: ID of pet to
return required: true type: integer format: int64 -
- name: petId in: path description: ID of pet to
return required: true type: integer format: int64 responses: -
- name: petId in: path description: ID of pet to
return required: true type: integer format: int64 responses: '200': -
- name: petId in: path description: ID of pet to
return required: true type: integer format: int64 responses: '200': description: successful operation -
- name: petId in: path description: ID of pet to
return required: true type: integer format: int64 responses: '200': description: successful operation '404': -
- name: petId in: path description: ID of pet to
return required: true type: integer format: int64 responses: '200': description: successful operation '404': description: Pet not found -
- name: petId in: path description: ID of pet to
return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "" '404': description: Pet not found -
- name: petId in: path description: ID of pet to
return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found -
public Pet getPet(final String id) { String https_url = "https:!//petstore.swagger.io/v2/pet/"
+ id; URL url; try { url = new URL(https_url); HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); if (con !!= null) { BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream())); String response = ""; String input; while ((input = br.readLine()) !!= null) { System.out.println(input); response += input; } br.close(); JSONObject object = new JSONObject(response); Pet result = new Pet(); result.setId(object.getInt("id")); result.setName(object.getString("name")); result.setStatus(object.getString("status")); JSONArray photos = object.getJSONArray("photoUrls"); List<String> photoArrays = new ArrayList!<>(); for (int i = 0; i < photos.length(); i!++) { photoArrays.add(photos.getString(i)); } result.setPhotoUrls(photoArrays); JSONArray tags = object.getJSONArray("tags"); List<String> tagArrays = new ArrayList!<>(); for (int i = 0; i < tags.length(); i!++) { tagArrays.add(tags.getString(i)); } result.setTags(tagArrays); System.out.println(result); System.out.println(result.getId()); System.out.println(result.getName()); System.out.println(result.getPhotoUrls().get(0)); System.out.println(result.getStatus()); System.out.println(result.getTags().get(0)); return result; } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } return null; } public class Pet { private Integer id; private String name; private List<String> photoUrls = null; private List<String> tags = null; private String status; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getPhotoUrls() { return photoUrls; } public void setPhotoUrls(List<String> photoUrls) { this.photoUrls = photoUrls; } public List<String> getTags() { return tags; } public void setTags(List<String> tags) { this.tags = tags; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } } fun getPet(id: String): Pet? { val https_url = "https:!//petstore.swagger.io/v2/pet/$id" val url: URL try { url = URL(https_url) val con = url.openConnection() as HttpsURLConnection val br = BufferedReader(InputStreamReader(con.inputStream)) var response = "" var input: String? = br.readLine() while (input !!= null) { println(input) response += input input = br.readLine() } br.close() val parsedObject = JSONObject(response) val photos = parsedObject.getJSONArray("photoUrls") val photoArrays = ArrayList<String>() for (i in 0 until photos.length()) { photoArrays.add(photos.getString(i)) } val tags = parsedObject.getJSONArray("tags") val tagArrays = ArrayList<String>() for (i in 0 until tags.length()) { tagArrays.add(tags.getString(i)) } val result = Pet( id = parsedObject.getInt("id"), name = parsedObject.getString("name"), status = parsedObject.getString("status"), photoUrls = photoArrays, tags = tagArrays ) println(result) println(result.id) println(result.name) println(result.photoUrls!!![0]) println(result.status) println(result.tags!!![0]) return result } catch (e: MalformedURLException) { e.printStackTrace() } catch (e: IOException) { e.printStackTrace() } catch (e: JSONException) { e.printStackTrace() } return null } data class Pet( var id: Int?, var name: String?, var photoUrls: List<String>?, var tags: List<String>?, var status: String? ) data class Tag(var id: Int?, var name: String?) fun getPet(id: String): Pet? { val https_url = "https:!//petstore.swagger.io/v2/pet/$id" val url: URL try { url = URL(https_url) val con = url.openConnection() as HttpsURLConnection val br = BufferedReader(InputStreamReader(con.inputStream)) var response = "" var input: String? = br.readLine() while (input !!= null) { println(input) response += input input = br.readLine() } br.close() val moshi = Moshi.Builder().build() val jsonAdapter = moshi.adapter<Pet>(Pet!::class.java) val pet = jsonAdapter.fromJson(response) println(pet) return pet } catch (e: MalformedURLException) { e.printStackTrace() } catch (e: IOException) { e.printStackTrace() } return null } data class Pet( var id: Int?, var name: String?, var photoUrls: List<String>?, var tags: List<Tag>?, var status: String? ) data class Tag(var id: Int?, var name: String?) fun getPet(id: String): Pet? { val client = OkHttpClient.Builder().build() val request = Request.Builder().url("https:!//petstore.swagger.io/v2/pet/$id").build() client.newCall(request).execute().use { val moshi = Moshi.Builder().build() val jsonAdapter = moshi.adapter<Pet>(Pet!::class.java) val pet = jsonAdapter.fromJson(it.body()!?.string()!!!) println(pet) return pet } } data class Pet( var id: Int?, var name: String?, var photoUrls: List<String>?, var tags: List<Tag>?, var status: String? ) data class Tag(var id: Int?, var name: String?) -
r.io/v2/pet/$id" tpsURLConnection eader(con.inputStream)) (Pet!::class.java) nse) g?) fun getPet(id: String): Pet?
{ val client = OkHttpClient.Builder().build() val request = Request.Builder().url("https:!//petstore.swagger.io/v2/pet/$id").build() client.newCall(request).execute().use { val moshi = Moshi.Builder().build() val jsonAdapter = moshi.adapter<Pet>(Pet!::class.java) val pet = jsonAdapter.fromJson(it.body()!?.string()!!!) println(pet) return pet } } data class Pet( var id: Int?, var name: String?, var photoUrls: List<String>?, var tags: List<Tag>?, var status: String? ) data class Tag(var id: Int?, var name: String?) -
r.io/v2/pet/$id" tpsURLConnection eader(con.inputStream)) (Pet!::class.java) nse) g?) fun getPet(id: String): Pet?
{ val client = OkHttpClient.Builder().build() val request = Request.Builder().url("https:!//petstore.swagger.io/v2/pet/$id").build() client.newCall(request).execute().use { val moshi = Moshi.Builder().build() val jsonAdapter = moshi.adapter<Pet>(Pet!::class.java) val pet = jsonAdapter.fromJson(it.body()!?.string()!!!) println(pet) return pet } } data class Pet( var id: Int?, var name: String?, var photoUrls: List<String>?, var tags: List<Tag>?, var status: String? ) data class Tag(var id: Int?, var name: String?) interface PetInterface { @GET("pet/{id}") fun getPet(@Path("id") id: String?) : Call<Pet> } .getPet(“42") -
On Github: swagger-api/swagger-codegen Generator & Templates Several templates already available
Command line tool SWAGGER CODEGEN Swagger Codegen java -jar swagger-codegen-cli-2.3.1.jar generate \ -i swagger.yaml \ --api-package com.yelp.codegen.sample.api \ --model-package com.yelp.codegen.sample.model \ --group-id com.yelp.codegen.sample \ --artifact-id sample-codegen \ --artifact-version 0.0.1 \ -l spring \ -o sample-codegen -
{{#model}}{{#description}} /** * {{description}} **/{{/description}} @ApiModel(description = "{{{description}}}") public class
{{classname}} {{#parent}}extends {{{parent}}}{{/parent}} { {{#vars}}{{#isEnum}} public enum {{datatypeWithEnum}} { {{#allowableValues}}{{#values}} {{•}}, {{/values}}{{/allowableValues}} }; @SerializedName("{{baseName}}") private {{{datatypeWithEnum}}} {{name}} = {{{defaultValue}}};{{/isEnum}}{{^isEnum}} @SerializedName("{{baseName}}") private {{{datatype}}} {{name}} = {{{defaultValue}}};{{/isEnum}}{{/vars}} {{#vars}} /**{{#description}} * {{{description}}}{{/description}}{{#minimum}} * minimum: {{minimum}}{{/minimum}}{{#maximum}} * maximum: {{maximum}}{{/maximum}} **/ @ApiModelProperty({{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") public {{{datatypeWithEnum}}} {{getter}}() { return {{name}}; } public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { this.{{name}} = {{name}}; } -
{{#model}}{{#description}} /** * {{description}} **/{{/description}} @ApiModel(description = "{{{description}}}") public class
{{classname}} {{#parent}}extends {{{p {{#vars}}{{#isEnum}} public enum {{datatypeWithEnum}} { {{#allowableValues}}{{#values}} {{•}}, {{/valu }; @SerializedName("{{baseName}}") private {{{datatypeWithEnum}}} {{name}} = {{{def -
{{#model}}{{#description}} /** * {{description}} **/{{/description}} @ApiModel(description = "{{{description}}}") public class
{{classname}} {{#parent}}extends {{{p {{#vars}}{{#isEnum}} public enum {{datatypeWithEnum}} { {{#allowableValues}}{{#values}} {{•}}, {{/valu }; @SerializedName("{{baseName}}") private {{{datatypeWithEnum}}} {{name}} = {{{def -
Plug it inside your gradle build Input/Output aware Simpler API
for the developer SWAGGER GRADLE CODEGEN Yelp/swagger-gradle-codegen A Gradle Plugin -
SWAGGER GRADLE CODEGEN Yelp/swagger-gradle-codegen Opinionated ✓ Kotlin ✓ RxJava2 ✓
Retrofit ✓ Moshi ✓ ThreeTenABP -
definitions: Pet: type: object required: - name - photoUrls properties:
id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string description: pet status in the store enum: - available - sold category: $ref: “#/definitions/Category" Category: type: object properties: id: type: integer format: int64 name: type: string -
Category: type: object properties: id: type: integer format: int64 name:
type: string class Category() -
Category: type: object properties: id: type: integer format: int64 name:
type: string data class Category() -
Category: type: object properties: id: type: integer format: int64 name:
type: string data class Category( var id, var name ) -
Category: type: object properties: id: type: integer format: int64 name:
type: string data class Category( var id: Long, var name: String ) -
Category: type: object properties: id: type: integer format: int64 name:
type: string data class Category( var id: Long?, var name: String? ) -
Category: type: object properties: id: type: integer format: int64 name:
type: string data class Category( var id: Long? = null, var name: String? = null ) -
Category: type: object properties: id: type: integer format: int64 name:
type: string data class Category( @Json(name = "id") var id: Long? = null, @Json(name = "name") var name: String? = null ) -
Category: type: object properties: id: type: integer format: int64 name:
type: string import com.squareup.moshi.Json data class Category( @Json(name = "id") var id: Long? = null, @Json(name = "name") var name: String? = null ) -
Category: type: object description: properties: id: type: integer description: format:
int64 name: type: string description: import com.squareup.moshi.Json data class Category( @Json(name = "id") var id: Long? = null, @Json(name = "name") var name: String? = null ) -
Category: type: object description: A Category used to group pets
properties: id: type: integer description: Unique ID of the Category format: int64 name: type: string description: Name of this category import com.squareup.moshi.Json data class Category( @Json(name = "id") var id: Long? = null, @Json(name = "name") var name: String? = null ) -
Category: type: object description: A Category used to group pets
properties: id: type: integer description: Unique ID of the Category format: int64 name: type: string description: Name of this category import com.squareup.moshi.Json /** * A Category used to group pets * @property id Unique ID of the Category * @property name Name of this category */ data class Category( @Json(name = "id") var id: Long? = null, @Json(name = "name") var name: String? = null ) -
definitions: Pet: type: object required: - name - photoUrls properties:
id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string enum: - available - sold category: $ref: “#/definitions/Category" -
definitions: Pet: type: object required: - name - photoUrls properties:
id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string enum: - available - sold category: $ref: “#/definitions/Category" package com.yelp.codegen.samples.models import com.squareup.moshi.Json data class Pet ( @Json(name = "name") var name: String, @Json(name = "photoUrls") var photoUrls: List<String>, @Json(name = "category") var category: Category? = null, @Json(name = "id") var id: Long? = null, @Json(name = "status") var status: Pet.StatusEnum? = null ) { enum class StatusEnum(val value: String){ @Json(name = "available") AVAILABLE("available"), @Json(name = "sold") SOLD("sold") } } -
definitions: Pet: type: object required: - name - photoUrls properties:
id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string enum: - available - sold category: $ref: “#/definitions/Category" package com.yelp.codegen.samples.models import com.squareup.moshi.Json data class Pet ( @Json(name = "name") var name: String, @Json(name = "photoUrls") var photoUrls: List<String>, @Json(name = "category") var category: Category? = null, @Json(name = "id") var id: Long? = null, @Json(name = "status") var status: Pet.StatusEnum? = null ) { enum class StatusEnum(val value: String){ @Json(name = "available") AVAILABLE("available"), @Json(name = "sold") SOLD("sold") } } -
definitions: Pet: type: object required: - name - photoUrls properties:
id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string enum: - available - sold category: $ref: “#/definitions/Category" package com.yelp.codegen.samples.models import com.squareup.moshi.Json data class Pet ( @Json(name = "name") var name: String, @Json(name = "photoUrls") var photoUrls: List<String>, @Json(name = "category") var category: Category? = null, @Json(name = "id") var id: Long? = null, @Json(name = "status") var status: Pet.StatusEnum? = null ) { enum class StatusEnum(val value: String){ @Json(name = "available") AVAILABLE("available"), @Json(name = "sold") SOLD("sold") } } -
definitions: Pet: type: object required: - name - photoUrls properties:
id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string enum: - available - sold category: $ref: “#/definitions/Category" package com.yelp.codegen.samples.models import com.squareup.moshi.Json data class Pet ( @Json(name = "name") var name: String, @Json(name = "photoUrls") var photoUrls: List<String>, @Json(name = "category") var category: Category? = null, @Json(name = "id") var id: Long? = null, @Json(name = "status") var status: Pet.StatusEnum? = null ) { enum class StatusEnum(val value: String){ @Json(name = "available") AVAILABLE("available"), @Json(name = "sold") SOLD("sold") } } -
definitions: Pet: type: object required: - name - photoUrls properties:
id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string enum: - available - sold category: $ref: “#/definitions/Category" package com.yelp.codegen.samples.models import com.squareup.moshi.Json data class Pet ( @Json(name = "name") var name: String, @Json(name = "photoUrls") var photoUrls: List<String>, @Json(name = "category") var category: Category? = null, @Json(name = "id") var id: Long? = null, @Json(name = "status") var status: Pet.StatusEnum? = null ) { enum class StatusEnum(val value: String){ @Json(name = "available") AVAILABLE("available"), @Json(name = "sold") SOLD("sold") } } -
definitions: Pet: type: object required: - name - photoUrls properties:
id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string enum: - available - sold category: $ref: “#/definitions/Category" package com.yelp.codegen.samples.models import com.squareup.moshi.Json data class Pet ( @Json(name = "name") var name: String, @Json(name = "photoUrls") var photoUrls: List<String>, @Json(name = "category") var category: Category? = null, @Json(name = "id") var id: Long? = null, @Json(name = "status") var status: Pet.StatusEnum? = null ) { enum class StatusEnum(val value: String){ @Json(name = "available") AVAILABLE("available"), @Json(name = "sold") SOLD("sold") } } -
definitions: Pet: type: object required: - name - photoUrls properties:
id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string enum: - available - sold category: $ref: “#/definitions/Category" package com.yelp.codegen.samples.models import com.squareup.moshi.Json /** * Represents a specific Pet in the store * @property category Optional category of the pet * @property id Unique ID of this Pet * @property name Name of this specific pet * @property photoUrls Photo URLs for this Pet on the bucket * @property status Pet status in the store */ data class Pet ( @Json(name = "name") var name: String, @Json(name = "photoUrls") var photoUrls: List<String>, @Json(name = "category") var category: Category? = null, @Json(name = "id") var id: Long? = null, @Json(name = "status") var status: Pet.StatusEnum? = null ) { /** * Pet status in the store * Values: AVAILABLE, SOLD */ enum class StatusEnum(val value: String){ @Json(name = "available") AVAILABLE("available"), @Json(name = "sold") SOLD("sold") } } -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found interface DefaultApi { } -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found interface DefaultApi { fun getPetById() } -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found interface DefaultApi { fun getPetById( @retrofit2.http.Path("petId") petId: Long ) } -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found interface DefaultApi { @GET("/pet/{petId}") fun getPetById( @retrofit2.http.Path("petId") petId: Long ) } -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found interface DefaultApi { @GET("/pet/{petId}") fun getPetById( @retrofit2.http.Path("petId") petId: Long ): Single<Pet> } -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found interface DefaultApi { @Headers( "X-Operation-ID: getPetById" ) @GET("/pet/{petId}") fun getPetById( @retrofit2.http.Path("petId") petId: Long ): Single<Pet> } -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found interface DefaultApi { /** * Find pet by ID * Returns a single pet * @param petId ID of pet to return (required) */ @Headers( "X-Operation-ID: getPetById" ) @GET("/pet/{petId}") fun getPetById( @retrofit2.http.Path("petId") petId: Long ): Single<Pet> } -
paths: /pet/{petId}: get: summary: Find pet by ID description: Returns
a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found package com.yelp.codegen.generatecodesamples.apis import com.yelp.codegen.generatecodesamples.models.Pet import io.reactivex.Single import retrofit2.http.GET import retrofit2.http.Headers interface DefaultApi { /** * Find pet by ID * Returns a single pet * @param petId ID of pet to return (required) */ @Headers( "X-Operation-ID: getPetById" ) @GET("/pet/{petId}") fun getPetById( @retrofit2.http.Path("petId") petId: Long ): Single<Pet> } -
Build an app module with specs locally Build a pure-Kotlin
module with a specs locally Build a library project that contains your models/apis Integrate your library with your CI system SWAGGER GRADLE CODEGEN Yelp/swagger-gradle-codegen Use cases -
buildscript { repositories { gradlePluginPortal() } dependencies { classpath "com.yelp.codegen:plugin:1.0.0"
} } generateSwagger { inputFile = file("../sample_specs.json") } -
buildscript { repositories { gradlePluginPortal() } dependencies { classpath "com.yelp.codegen:plugin:1.0.0"
} } generateSwagger { inputFile = file("../sample_specs.json") outputDir = file("./src/main/java/") } -
buildscript { repositories { gradlePluginPortal() } dependencies { classpath "com.yelp.codegen:plugin:1.0.0"
} } generateSwagger { platform = "kotlin" packageName = "com.yelp.codegen.samples" specName = "petstore" specVersion = "1.0.0" inputFile = file("../sample_specs.json") outputDir = file("./src/main/java/") } -
buildscript { repositories { gradlePluginPortal() } dependencies { classpath "com.yelp.codegen:plugin:1.0.0"
} } generateSwagger { platform = "kotlin" packageName = "com.yelp.codegen.samples" specName = "petstore" specVersion = "1.0.0" inputFile = file("../sample_specs.json") outputDir = file("./src/main/java/") } -
buildscript { repositories { gradlePluginPortal() } dependencies { classpath "com.yelp.codegen:plugin:1.0.0"
} } generateSwagger { platform = "kotlin" packageName = "com.yelp.codegen.samples" specName = "petstore" specVersion = "1.0.0" inputFile = file("../sample_specs.json") outputDir = file("./src/main/java/") } -
buildscript { repositories { gradlePluginPortal() } dependencies { classpath "com.yelp.codegen:plugin:1.0.0"
} } generateSwagger { platform = "kotlin" packageName = "com.yelp.codegen.samples" specName = "petstore" specVersion = "1.0.0" inputFile = file("../sample_specs.json") outputDir = file("./src/main/java/") } preBuild.dependsOn(tasks.getByName(“generateSwagger")) -
e pet of pet to return (required) ion-ID: getPetById") ")
trofit2.http.Path("petId") petId: Long): Single<Pet> eup.moshi.Json "name") var name: String, "photoUrls") var photoUrls: List<String>, "category") var category: Category? = null, "id") var id: Long? = null, "status") var status: Pet.StatusEnum? = null tatusEnum(val value: String){ me = "available") AVAILABLE("available"), me = "sold") SOLD("sold") -
Breaking changes Defining names Accessing the Raw Response SWAGGER GRADLE
CODEGEN Yelp/swagger-gradle-codegen Challenges interface DefaultApi { /** * Find the owner of a pet. !*/ @GET("/pet/owner") fun getPetById( @retrofit2.http.Path("name") name: String @retrofit2.http.Path("surname") surname: String ): Single<Owner> } interface DefaultApi { /** * Find the owner of a pet. !*/ @GET("/pet/owner") fun getPetById( @retrofit2.http.Path("surname") surname: String @retrofit2.http.Path("name") name: String ): Single<Owner> } data class IdToPredictedBizInfoForPhotoUploadSuggestionMapToBusinessReviewMap( !!... ) interface DefaultApi { /** * Find the owner of a pet. !*/ @GET("/pet/owner") fun getPetById( @retrofit2.http.Path("surname") surname: String @retrofit2.http.Path("name") name: String ): Single<Owner> } interface DefaultApi { /** * Find the owner of a pet. !*/ @GET("/pet/owner") fun getPetById( @retrofit2.http.Path("surname") surname: String @retrofit2.http.Path("name") name: String ): Single<Result<Owner!>> } -
Support Inheritance Coroutines iOS Template Getting a Corgi SWAGGER GRADLE
CODEGEN Yelp/swagger-gradle-codegen Future