Skip to content

Commit 46c18ad

Browse files
Ramanthwing328
authored andcommitted
[R] feat(r) : Alternate PR for serialization fixes along with WithHttpInfo method enhancement (#3099)
* feat(r): fixing serialization and deserialization issues * feat(r): pet store file generated with serialization fixes * fix(r): updated the query params with keyname in get request * fix(r):fix issue with package name and other minor * fix(r): fixing unit tests * feat(r): adding api calls WithHttpInfo method * fix(r): reverting unit test changes * feat(r): saving changes for reference * Revert "feat(r): saving changes for reference" This reverts commit 0d091b5. * feat(r): minor refactor of method position * fix(r): fixing bug in withhttpinfo method args passing * fix(r): generated petstore with fix
1 parent 8e0dc2f commit 46c18ad

File tree

19 files changed

+641
-234
lines changed

19 files changed

+641
-234
lines changed

bin/windows/r-petstore.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ If Not Exist %executable% (
55
)
66

77
REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -DloggerPath=conf/log4j.properties
8-
set ags=generate -i modules\openapi-generator\src\test\resources\2_0\petstore.yaml -g r -o samples\client\petstore\R
8+
set ags=generate -i modules\openapi-generator\src\test\resources\2_0\petstore.yaml -g r -o samples\client\petstore\R --additional-properties packageName=petstore
99

1010
java %JAVA_OPTS% -jar %executable% %ags%

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RClientCodegen.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,10 @@ public RClientCodegen() {
103103
typeMapping.put("file", "data.frame");
104104
typeMapping.put("binary", "data.frame");
105105
typeMapping.put("ByteArray", "character");
106-
typeMapping.put("map", "object");
106+
typeMapping.put("map", "map");
107+
typeMapping.put("object", "object");
107108

109+
importMapping.clear();
108110
cliOptions.clear();
109111
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "R package name (convention: lowercase).")
110112
.defaultValue("openapi"));
@@ -288,10 +290,10 @@ public String getTypeDeclaration(Schema p) {
288290
if (ModelUtils.isArraySchema(p)) {
289291
ArraySchema ap = (ArraySchema) p;
290292
Schema inner = ap.getItems();
291-
return getTypeDeclaration(inner);
293+
return getSchemaType(p) + "[" + getTypeDeclaration(inner)+ "]";
292294
} else if (ModelUtils.isMapSchema(p)) {
293295
Schema inner = ModelUtils.getAdditionalProperties(p);
294-
return getTypeDeclaration(inner);
296+
return getSchemaType(p) + "(" + getTypeDeclaration(inner) + ")";
295297
}
296298

297299
// Not using the supertype invocation, because we want to UpperCamelize

modules/openapi-generator/src/main/resources/r/api.mustache

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@
3333
},
3434
{{#operation}}
3535
{{{operationId}}} = function({{#requiredParams}}{{paramName}}, {{/requiredParams}}{{#optionalParams}}{{paramName}}={{^defaultValue}}NULL{{/defaultValue}}{{#defaultValue}}{{{.}}}{{/defaultValue}}, {{/optionalParams}}...){
36+
apiResponse <- self${{{operationId}}}WithHttpInfo({{#allParams}}{{paramName}}, {{/allParams}}...)
37+
resp <- apiResponse$response
38+
if (httr::status_code(resp) >= 200 && httr::status_code(resp) <= 299) {
39+
apiResponse$content
40+
} else if (httr::status_code(resp) >= 400 && httr::status_code(resp) <= 499) {
41+
apiResponse
42+
} else if (httr::status_code(resp) >= 500 && httr::status_code(resp) <= 599) {
43+
apiResponse
44+
}
45+
},
46+
47+
{{{operationId}}}WithHttpInfo = function({{#requiredParams}}{{paramName}}, {{/requiredParams}}{{#optionalParams}}{{paramName}}={{^defaultValue}}NULL{{/defaultValue}}{{#defaultValue}}{{{.}}}{{/defaultValue}}, {{/optionalParams}}...){
3648
args <- list(...)
3749
queryParams <- list()
3850
headerParams <- c()
@@ -119,21 +131,23 @@
119131
if (httr::status_code(resp) >= 200 && httr::status_code(resp) <= 299) {
120132
{{#returnType}}
121133
{{#isPrimitiveType}}
122-
httr::content(resp, "text", encoding = "UTF-8"
134+
content <- httr::content(resp, "text", encoding = "UTF-8")
135+
ApiResponse$new(content,resp)
123136
{{/isPrimitiveType}}
124137
{{^isPrimitiveType}}
125-
{{returnType}}$new()$fromJSONString(httr::content(resp, "text", encoding = "UTF-8"))
138+
deserializedRespObj <- self$apiClient$deserialize(resp, "{{returnType}}", "package:{{packageName}}")
139+
ApiResponse$new(deserializedRespObj, resp)
126140
{{/isPrimitiveType}}
127141
{{/returnType}}
128142
{{^returnType}}
129-
# void response, no need to return anything
143+
{{! Returning the ApiResponse object with NULL object when the endpoint doesn't return anything}}
144+
ApiResponse$new(NULL, resp)
130145
{{/returnType}}
131146
} else if (httr::status_code(resp) >= 400 && httr::status_code(resp) <= 499) {
132147
ApiResponse$new("API client error", resp)
133148
} else if (httr::status_code(resp) >= 500 && httr::status_code(resp) <= 599) {
134149
ApiResponse$new("API server error", resp)
135150
}
136-
137151
}{{#hasMore}},{{/hasMore}}
138152
{{/operation}}
139153
)

modules/openapi-generator/src/main/resources/r/api_client.mustache

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ ApiClient <- R6::R6Class(
7474
headers <- httr::add_headers(c(headerParams, self$defaultHeaders))
7575

7676
if (method == "GET") {
77-
httr::GET(url, queryParams, headers, ...)
77+
httr::GET(url, query = queryParams, headers, ...)
7878
} else if (method == "POST") {
7979
httr::POST(url, query = queryParams, headers, body = body, httr::content_type("application/json"), ...)
8080
} else if (method == "PUT") {
@@ -88,6 +88,48 @@ ApiClient <- R6::R6Class(
8888
} else {
8989
stop("http method must be `GET`, `HEAD`, `OPTIONS`, `POST`, `PATCH`, `PUT` or `DELETE`.")
9090
}
91+
},
92+
93+
deserialize = function(resp, returnType, pkgEnv) {
94+
respObj <- jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"))
95+
self$deserializeObj(respObj, returnType, pkgEnv)
96+
},
97+
98+
deserializeObj = function(obj, returnType, pkgEnv) {
99+
returnObj <- NULL
100+
primitiveTypes <- c("character", "numeric", "integer", "logical", "complex")
101+
102+
if (startsWith(returnType, "map(")) {
103+
innerReturnType <- regmatches(returnType, regexec(pattern = "map\\((.*)\\)", returnType))[[1]][2]
104+
returnObj <- lapply(names(obj), function(name) {
105+
self$deserializeObj(obj[[name]], innerReturnType, pkgEnv)
106+
})
107+
names(returnObj) <- names(obj)
108+
} else if (startsWith(returnType, "array[")) {
109+
innerReturnType <- regmatches(returnType, regexec(pattern = "array\\[(.*)\\]", returnType))[[1]][2]
110+
if (c(innerReturnType) %in% primitiveTypes) {
111+
returnObj <- vector("list", length = length(obj))
112+
if (length(obj) > 0) {
113+
for (row in 1:length(obj)) {
114+
returnObj[[row]] <- self$deserializeObj(obj[row], innerReturnType, pkgEnv)
115+
}
116+
}
117+
} else {
118+
returnObj <- vector("list", length = nrow(obj))
119+
if (nrow(obj) > 0) {
120+
for (row in 1:nrow(obj)) {
121+
returnObj[[row]] <- self$deserializeObj(obj[row, , drop = FALSE], innerReturnType, pkgEnv)
122+
}
123+
}
124+
}
125+
} else if (exists(returnType, pkgEnv) && !(c(returnType) %in% primitiveTypes)) {
126+
returnType <- get(returnType, envir = as.environment(pkgEnv))
127+
returnObj <- returnType$new()
128+
returnObj$fromJSON(jsonlite::toJSON(obj, digits = NA))
129+
} else {
130+
returnObj <- obj
131+
}
132+
returnObj
91133
}
92134
)
93135
)

modules/openapi-generator/src/main/resources/r/model.mustache

Lines changed: 39 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -132,99 +132,79 @@
132132
{{classname}}Object <- jsonlite::fromJSON({{classname}}Json)
133133
{{#vars}}
134134
if (!is.null({{classname}}Object$`{{baseName}}`)) {
135-
{{#isListContainer}}
136-
{{#isPrimitiveType}}
137-
self$`{{baseName}}` <- {{classname}}Object$`{{baseName}}`
138-
{{/isPrimitiveType}}
139-
{{^isPrimitiveType}}
140-
self$`{{baseName}}` <- sapply({{classname}}Object$`{{baseName}}`, function(x) {
141-
{{baseName}}Object <- {{dataType}}$new()
142-
{{baseName}}Object$fromJSON(jsonlite::toJSON(x, auto_unbox = TRUE))
143-
{{baseName}}Object
144-
})
145-
{{/isPrimitiveType}}
146-
{{/isListContainer}}
147-
{{^isListContainer}}
135+
{{#isContainer}}
136+
self$`{{baseName}}` <- ApiClient$new()$deserializeObj({{classname}}Object$`{{baseName}}`, "{{dataType}}", "package:{{packageName}}")
137+
{{/isContainer}}
138+
{{^isContainer}}
148139
{{#isPrimitiveType}}
149140
self$`{{baseName}}` <- {{classname}}Object$`{{baseName}}`
150141
{{/isPrimitiveType}}
151142
{{^isPrimitiveType}}
152143
{{baseName}}Object <- {{dataType}}$new()
153-
{{baseName}}Object$fromJSON(jsonlite::toJSON({{classname}}Object${{baseName}}, auto_unbox = TRUE))
144+
{{baseName}}Object$fromJSON(jsonlite::toJSON({{classname}}Object${{baseName}}, auto_unbox = TRUE, digits = NA))
154145
self$`{{baseName}}` <- {{baseName}}Object
155146
{{/isPrimitiveType}}
156-
{{/isListContainer}}
147+
{{/isContainer}}
157148
}
158149
{{/vars}}
159150
},
160151
toJSONString = function() {
161-
sprintf(
162-
'{
163-
{{#vars}}
164-
"{{baseName}}":
165-
{{#isListContainer}}
166-
{{#isPrimitiveType}}
167-
{{#isNumeric}}[%d]{{/isNumeric}}{{^isNumeric}}[%s]{{/isNumeric}}{{#hasMore}},{{/hasMore}}
168-
{{/isPrimitiveType}}
169-
{{^isPrimitiveType}}
170-
[%s]{{#hasMore}},{{/hasMore}}
171-
{{/isPrimitiveType}}
172-
{{/isListContainer}}
173-
{{^isListContainer}}
174-
{{#isPrimitiveType}}
175-
{{#isNumeric}}%d{{/isNumeric}}{{^isNumeric}}"%s"{{/isNumeric}}{{#hasMore}},{{/hasMore}}
176-
{{/isPrimitiveType}}
177-
{{^isPrimitiveType}}
178-
%s{{#hasMore}},{{/hasMore}}
179-
{{/isPrimitiveType}}
180-
{{/isListContainer}}
181-
{{/vars}}
182-
}',
183-
{{#vars}}
152+
jsoncontent <- c(
153+
{{#vars}}
154+
if (!is.null(self$`{{baseName}}`)) {
155+
sprintf(
156+
'"{{baseName}}":
157+
{{#isListContainer}}
158+
{{#isPrimitiveType}}
159+
{{#isNumeric}}[%d]{{/isNumeric}}{{^isNumeric}}[%s]{{/isNumeric}}
160+
{{/isPrimitiveType}}
161+
{{^isPrimitiveType}}[%s]
162+
{{/isPrimitiveType}}
163+
{{/isListContainer}}
164+
{{^isListContainer}}
165+
{{#isPrimitiveType}}
166+
{{#isNumeric}}%d{{/isNumeric}}{{^isNumeric}}"%s"{{/isNumeric}}
167+
{{/isPrimitiveType}}
168+
{{^isPrimitiveType}}%s
169+
{{/isPrimitiveType}}
170+
{{/isListContainer}}',
184171
{{#isListContainer}}
185172
{{#isPrimitiveType}}
186-
paste(unlist(lapply(self$`{{{baseName}}}`, function(x) paste0('"', x, '"'))), collapse=","){{#hasMore}},{{/hasMore}}
173+
paste(unlist(lapply(self$`{{{baseName}}}`, function(x) paste0('"', x, '"'))), collapse=",")
187174
{{/isPrimitiveType}}
188175
{{^isPrimitiveType}}
189-
paste(unlist(lapply(self$`{{{baseName}}}`, function(x) jsonlite::toJSON(x$toJSON(), auto_unbox=TRUE))), collapse=","){{#hasMore}},{{/hasMore}}
176+
paste(unlist(lapply(self$`{{{baseName}}}`, function(x) jsonlite::toJSON(x$toJSON(), auto_unbox=TRUE, digits = NA))), collapse=",")
190177
{{/isPrimitiveType}}
191178
{{/isListContainer}}
192179
{{^isListContainer}}
193180
{{#isPrimitiveType}}
194-
self$`{{baseName}}`{{#hasMore}},{{/hasMore}}
181+
self$`{{baseName}}`
195182
{{/isPrimitiveType}}
196183
{{^isPrimitiveType}}
197-
jsonlite::toJSON(self$`{{baseName}}`$toJSON(), auto_unbox=TRUE){{#hasMore}},{{/hasMore}}
184+
jsonlite::toJSON(self$`{{baseName}}`$toJSON(), auto_unbox=TRUE, digits = NA)
198185
{{/isPrimitiveType}}
199186
{{/isListContainer}}
187+
)}{{#hasMore}},{{/hasMore}}
200188
{{/vars}}
201189
)
190+
jsoncontent <- paste(jsoncontent, collapse = ",")
191+
paste('{', jsoncontent, '}', sep = "")
202192
},
203193
fromJSONString = function({{classname}}Json) {
204194
{{classname}}Object <- jsonlite::fromJSON({{classname}}Json)
205195
{{#vars}}
206-
{{#isListContainer}}
207-
{{#isPrimitiveType}}
208-
self$`{{baseName}}` <- lapply({{classname}}Object$`{{baseName}}`, function (x) x)
209-
{{/isPrimitiveType}}
210-
{{^isPrimitiveType}}
211-
data.frame <- {{classname}}Object$`{{baseName}}`
212-
self$`{{baseName}}` <- vector("list", length = nrow(data.frame))
213-
for (row in 1:nrow(data.frame)) {
214-
{{baseName}}.node <- {{dataType}}$new()
215-
{{baseName}}.node$fromJSON(jsonlite::toJSON(data.frame[row,,drop = TRUE], auto_unbox = TRUE))
216-
self$`{{baseName}}`[[row]] <- {{baseName}}.node
217-
}
218-
{{/isPrimitiveType}}
219-
{{/isListContainer}}
220-
{{^isListContainer}}
196+
{{! AAPI - added condition for handling container type of parameters, map and array}}
197+
{{#isContainer}}
198+
self$`{{baseName}}` <- ApiClient$new()$deserializeObj({{classname}}Object$`{{baseName}}`, "{{dataType}}","package:{{packageName}}")
199+
{{/isContainer}}
200+
{{^isContainer}}
221201
{{#isPrimitiveType}}
222202
self$`{{baseName}}` <- {{classname}}Object$`{{baseName}}`
223203
{{/isPrimitiveType}}
224204
{{^isPrimitiveType}}
225-
self$`{{baseName}}` <- {{dataType}}$new()$fromJSON(jsonlite::toJSON({{classname}}Object${{baseName}}, auto_unbox = TRUE))
205+
self$`{{baseName}}` <- {{dataType}}$new()$fromJSON(jsonlite::toJSON({{classname}}Object${{baseName}}, auto_unbox = TRUE, digits = NA))
226206
{{/isPrimitiveType}}
227-
{{/isListContainer}}
207+
{{/isContainer}}
228208
{{/vars}}
229209
self
230210
}

samples/client/petstore/R/R/api_client.R

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ ApiClient <- R6::R6Class(
8181
headers <- httr::add_headers(c(headerParams, self$defaultHeaders))
8282

8383
if (method == "GET") {
84-
httr::GET(url, queryParams, headers, ...)
84+
httr::GET(url, query = queryParams, headers, ...)
8585
} else if (method == "POST") {
8686
httr::POST(url, query = queryParams, headers, body = body, httr::content_type("application/json"), ...)
8787
} else if (method == "PUT") {
@@ -95,6 +95,48 @@ ApiClient <- R6::R6Class(
9595
} else {
9696
stop("http method must be `GET`, `HEAD`, `OPTIONS`, `POST`, `PATCH`, `PUT` or `DELETE`.")
9797
}
98+
},
99+
100+
deserialize = function(resp, returnType, pkgEnv) {
101+
respObj <- jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"))
102+
self$deserializeObj(respObj, returnType, pkgEnv)
103+
},
104+
105+
deserializeObj = function(obj, returnType, pkgEnv) {
106+
returnObj <- NULL
107+
primitiveTypes <- c("character", "numeric", "integer", "logical", "complex")
108+
109+
if (startsWith(returnType, "map(")) {
110+
innerReturnType <- regmatches(returnType, regexec(pattern = "map\\((.*)\\)", returnType))[[1]][2]
111+
returnObj <- lapply(names(obj), function(name) {
112+
self$deserializeObj(obj[[name]], innerReturnType, pkgEnv)
113+
})
114+
names(returnObj) <- names(obj)
115+
} else if (startsWith(returnType, "array[")) {
116+
innerReturnType <- regmatches(returnType, regexec(pattern = "array\\[(.*)\\]", returnType))[[1]][2]
117+
if (c(innerReturnType) %in% primitiveTypes) {
118+
returnObj <- vector("list", length = length(obj))
119+
if (length(obj) > 0) {
120+
for (row in 1:length(obj)) {
121+
returnObj[[row]] <- self$deserializeObj(obj[row], innerReturnType, pkgEnv)
122+
}
123+
}
124+
} else {
125+
returnObj <- vector("list", length = nrow(obj))
126+
if (nrow(obj) > 0) {
127+
for (row in 1:nrow(obj)) {
128+
returnObj[[row]] <- self$deserializeObj(obj[row, , drop = FALSE], innerReturnType, pkgEnv)
129+
}
130+
}
131+
}
132+
} else if (exists(returnType, pkgEnv) && !(c(returnType) %in% primitiveTypes)) {
133+
returnType <- get(returnType, envir = as.environment(pkgEnv))
134+
returnObj <- returnType$new()
135+
returnObj$fromJSON(jsonlite::toJSON(obj, digits = NA))
136+
} else {
137+
returnObj <- obj
138+
}
139+
returnObj
98140
}
99141
)
100142
)

samples/client/petstore/R/R/category.R

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,24 @@ Category <- R6::R6Class(
5454
}
5555
},
5656
toJSONString = function() {
57-
sprintf(
58-
'{
59-
"id":
60-
%d,
61-
"name":
62-
"%s"
63-
}',
64-
self$`id`,
57+
jsoncontent <- c(
58+
if (!is.null(self$`id`)) {
59+
sprintf(
60+
'"id":
61+
%d
62+
',
63+
self$`id`
64+
)},
65+
if (!is.null(self$`name`)) {
66+
sprintf(
67+
'"name":
68+
"%s"
69+
',
6570
self$`name`
71+
)}
6672
)
73+
jsoncontent <- paste(jsoncontent, collapse = ",")
74+
paste('{', jsoncontent, '}', sep = "")
6775
},
6876
fromJSONString = function(CategoryJson) {
6977
CategoryObject <- jsonlite::fromJSON(CategoryJson)

0 commit comments

Comments
 (0)