-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[R] Add new R client generator #6351
Conversation
if (httr::status_code(resp) >= 200 && httr::status_code(resp) <= 299) { | ||
parsed <- jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"), | ||
simplifyVector = FALSE) | ||
result <- Pet$fromJSON(parsed) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ramnov is there any way we can provide a fromJSON
method to construct the object based on a JSON string?
For other languages, there are libraries for (de)serialization between JSON and object. I wonder if R has similar package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no package in R to deserialize/serialize between R6 object and JSON. fromJSON() and toJSON() methods have to be implemented by ourselves in R6 Classes. I believe Pet.R already has a toJSON() method. Can you add this fromJSON() method as well to Pet Class in Pet.R :
fromJSON = function(petJson) {
petObject <- jsonlite::fromJSON(petJson)
self$id <- petObject$id
self$category <- Element$new(petObject$category$id, petObject$category$name)
self$name <- petObject$name
self$photoUrls <- petObject$photoUrls
self$tags <- lapply(petObject$tags, function(x) Element$new(x$id, x$name))
self$status <- petObject$status
}
And then this function can be used in PetApi.R like this :
result <- Pet$new()$fromJSON(httr::content(resp, "text", encoding = "UTF-8"),
simplifyVector = FALSE)
resp <- httr::GET(paste0(self$url), | ||
httr::add_headers("User-Agent" = self$userAgent, "content-type" = "application/xml") | ||
) | ||
# TODO add support for query parameters "status" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ramnov I'm not sure how query string can be added to httpr
? Is there something like httr::add_queries
? I couldn't find one in https://www.rdocumentation.org/packages/httr/versions/1.2.1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a query parameter in GET function.
Example : GET("http://httpbin.org/cookies/set", query = list(a = 1, b = 2))
will translate to http://httpbin.org/cookies/set?a=1&b=1
More Examples here : https://stackoverflow.com/questions/32742535/difference-between-query-and-body-in-httrpost
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ramnov OK. Will give that a try.
basePath = NULL, | ||
scheme = NULL, | ||
url = NULL, | ||
initialize = function(host, basePath, scheme){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ramnov Can host
, basePath
, scheme
be optional and we'll provide the default value based on the spec? For example, the default value for basePath is v2
: https://github.com/swagger-api/swagger-codegen/blob/master/modules/swagger-codegen/src/test/resources/2_0/petstore.yaml#L13
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
default values can be set during definition itself. To allow for optional arguments in initialize function, we just need to check whether the argument is "missing". Here is an example of setting default values and optional arguments in PetApi class :
PetApi <- R6::R6Class(
'PetApi',
public = list(
userAgent = "Swagger-Codegen/1.0.0/r",
host = "petstore.swagger.io",
basePath = "v2",
scheme = "http",
url = NULL,
initialize = function(host, basePath, scheme){
if (!missing(host)) {
stopifnot(is.character(host), length(host) == 1)
self$host <- host
}
if (!missing(basePath)) {
stopifnot(is.character(basePath), length(basePath) == 1)
self$basePath <- basePath
}
if (!missing(scheme)) {
stopifnot(is.character(scheme), length(scheme) == 1)
self$scheme <- scheme
}
self$url <- sprintf("%s://%s/%s/pet/", scheme, host, basePath)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. Will incorporate these changes later today.
parsed <- jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"), | ||
simplifyVector = FALSE) | ||
result <- {{returnType}}$fromJSON(parsed) | ||
result <- {{returnType}}$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{{returnType}}$new()$fromJSON
{{/isPrimitiveType}} | ||
{{^isPrimitiveType}} | ||
{{#isListContainer}} | ||
self${{name}} <- lapply({{classname}}Object${{name}}, function(x) {{datatype}}$new()$fromJSON(x) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, you are passing a data frame to fromJSON method. You should pass a JSON string like this :
self${{name}} <- lapply({{classname}}Object${{name}}, function(x) {{datatype}}$new()$fromJSON(jsonlite::toJSON(x))
self$id <- OrderObject$id | ||
self$pet_id <- OrderObject$pet_id | ||
self$quantity <- OrderObject$quantity | ||
self$ship_date <- Date$new()$fromJSON(OrderObject$ship_date) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again you need to pass JSON to fromJSON rather than data frame :
Date$new()$fromJSON(jsonlite::toJSON(OrderObject$ship_date))
fromJSON = function(PetJson) { | ||
PetObject <- jsonlite::fromJSON(PetJson) | ||
self$id <- PetObject$id | ||
self$category <- Category$new()$fromJSON(PetObject$category) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Category$new()$fromJSON(jsonlite::toJSON(PetObject$category))
self$category <- Category$new()$fromJSON(PetObject$category) | ||
self$name <- PetObject$name | ||
self$photo_urls <- PetObject$photo_urls | ||
self$tags <- lapply(PetObject$tags, function(x) Tag$new()$fromJSON(x) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self$tags <- lapply(PetObject$tags, function(x) Tag$new()$fromJSON(jsonlite::toJSON(x))
parsed <- jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"), | ||
simplifyVector = FALSE) | ||
result <- Pet$fromJSON(parsed) | ||
result <- Pet$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
result <- Pet$new()$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE)
parsed <- jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"), | ||
simplifyVector = FALSE) | ||
result <- Pet$fromJSON(parsed) | ||
result <- Pet$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
result <- Pet$new()$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE)
parsed <- jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"), | ||
simplifyVector = FALSE) | ||
result <- Pet$fromJSON(parsed) | ||
result <- Pet$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
result <- Pet$new()$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE)
parsed <- jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"), | ||
simplifyVector = FALSE) | ||
result <- ApiResponse$fromJSON(parsed) | ||
result <- ApiResponse$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
result <- ApiResponse$new()$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE)
parsed <- jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"), | ||
simplifyVector = FALSE) | ||
result <- Integer$fromJSON(parsed) | ||
result <- Integer$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
result <- Integer$new()$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE)
parsed <- jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"), | ||
simplifyVector = FALSE) | ||
result <- Order$fromJSON(parsed) | ||
result <- Order$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
result <- Order$new()$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE)
parsed <- jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"), | ||
simplifyVector = FALSE) | ||
result <- Order$fromJSON(parsed) | ||
result <- Order$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
result <- Order$new()$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE)
parsed <- jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"), | ||
simplifyVector = FALSE) | ||
result <- User$fromJSON(parsed) | ||
result <- User$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
result <- User$new()$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE)
parsed <- jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"), | ||
simplifyVector = FALSE) | ||
result <- Character$fromJSON(parsed) | ||
result <- Character$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
result <- Character$new()$fromJSON(httr::content(resp, "text", encoding = "UTF-8"), simplifyVector = FALSE)
self${{name}} <- lapply({{classname}}Object${{name}}, function(x) {{datatype}}$new()$fromJSON(x) | ||
{{/isListContainer}} | ||
{{^isListContainer}} | ||
self${{name}} <- {{datatype}}$new()$fromJSON({{classname}}Object${{name}}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self${{name}} <- {{datatype}}$new()$fromJSON(jsonlite::toJSON({{classname}}Object${{name}}))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will also change line 88 from
self${{name}} <- lapply({{classname}}Object${{name}}, function(x) {{datatype}}$new()$fromJSON(x)
to
self${{name}} <- lapply({{classname}}Object${{name}}, function(x) {{datatype}}$new()$fromJSON(jsonlite::toJSON(x))
"{{baseName}}" = {{paramName}}{{#hasMore}},{{/hasMore}} | ||
{{/isFile}} | ||
{{#isFile}} | ||
"{{baseName}}" = upload_file({{paramName}}){{#hasMore}},{{/hasMore}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
httr::upload_file
@@ -134,7 +134,7 @@ PetApi <- R6::R6Class( | |||
httr::add_headers("User-Agent" = self$userAgent, "accept" = "multipart/form-data", "content-type" = "application/json") | |||
,body = list( | |||
"additionalMetadata" = additional_metadata, | |||
"file" = file #TODO support file upload | |||
"file" = upload_file(file) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
httr::upload_file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed via d76ab6d
PR checklist
./bin/
to update Petstore sample so that CIs can verify the change. (For instance, only need to run./bin/{LANG}-petstore.sh
and./bin/security/{LANG}-petstore.sh
if updating the {LANG} (e.g. php, ruby, python, etc) code generator or {LANG} client's mustache templates). Windows batch files can be found in.\bin\windows\
.3.0.0
branch for breaking (non-backward compatible) changes.Description of the PR
Add R client generator based on R Petstore client provided by @ramnov
Still WIP