Skip to content

Commit c56ea55

Browse files
authored
[R] avoid to-JSON issues when R6 classes contain lists of R6 classes (#22828)
* [R] avoid to-JSON issues when R6 classes contain lists of R6 classes * fix missing comma * only include extractor methods when they are needed * regenerate samples * fix typo
1 parent a625300 commit c56ea55

File tree

13 files changed

+304
-18
lines changed

13 files changed

+304
-18
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,17 +601,25 @@ public String toOperationId(String operationId) {
601601
public ModelsMap postProcessModels(ModelsMap objs) {
602602
for (ModelMap mo : objs.getModels()) {
603603
CodegenModel cm = mo.getModel();
604+
boolean needsExtractSimpleType = false;
604605
for (CodegenProperty var : cm.vars) {
605606
// check to see if base name is an empty string
606607
if ("".equals(var.baseName)) {
607608
LOGGER.debug("Empty baseName `` (empty string) in the model `{}` has been renamed to `empty_string` to avoid compilation errors.", cm.classname);
608609
var.baseName = "empty_string";
609610
}
610611

612+
if (!var.isPrimitiveType) {
613+
needsExtractSimpleType = true;
614+
}
615+
611616
// create extension x-r-doc-type to store the data type in r doc format
612617
var.vendorExtensions.put("x-r-doc-type", constructRdocType(var));
613618
}
614619

620+
// create extension x-r-has-non-primitive-field to indicate whether generated models need special handling for complex types
621+
cm.vendorExtensions.put("x-r-has-non-primitive-field", needsExtractSimpleType);
622+
615623
// apply the same fix, enhancement for allVars
616624
for (CodegenProperty var : cm.allVars) {
617625
// check to see if base name is an empty string

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

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,15 +242,15 @@
242242
self$`{{name}}`
243243
{{/isPrimitiveType}}
244244
{{^isPrimitiveType}}
245-
lapply(self$`{{name}}`, function(x) x$toSimpleType())
245+
self$extractSimpleType(self$`{{name}}`)
246246
{{/isPrimitiveType}}
247247
{{/isArray}}
248248
{{#isMap}}
249249
{{#isPrimitiveType}}
250250
self$`{{name}}`
251251
{{/isPrimitiveType}}
252252
{{^isPrimitiveType}}
253-
lapply(self$`{{name}}`, function(x) x$toSimpleType())
253+
self$extractSimpleType(self$`{{name}}`)
254254
{{/isPrimitiveType}}
255255
{{/isMap}}
256256
{{/isContainer}}
@@ -259,7 +259,7 @@
259259
self$`{{name}}`
260260
{{/isPrimitiveType}}
261261
{{^isPrimitiveType}}
262-
self$`{{name}}`$toSimpleType()
262+
self$extractSimpleType(self$`{{name}}`)
263263
{{/isPrimitiveType}}
264264
{{/isContainer}}
265265
}
@@ -272,6 +272,31 @@
272272
{{/isAdditionalPropertiesTrue}}
273273
return({{classname}}Object)
274274
},
275+
{{#vendorExtensions.x-r-has-non-primitive-field}}
276+
277+
extractSimpleType = function(x) {
278+
if (R6::is.R6(x)) {
279+
return(x$toSimpleType())
280+
} else if (!self$hasNestedR6(x)) {
281+
return(x)
282+
}
283+
lapply(x, self$extractSimpleType)
284+
},
285+
286+
hasNestedR6 = function(x) {
287+
if (R6::is.R6(x)) {
288+
return(TRUE)
289+
}
290+
if (is.list(x)) {
291+
for (item in x) {
292+
if (self$hasNestedR6(item)) {
293+
return(TRUE)
294+
}
295+
}
296+
}
297+
FALSE
298+
},
299+
{{/vendorExtensions.x-r-has-non-primitive-field}}
275300
276301
#' @description
277302
#' Deserialize JSON string into an instance of {{{classname}}}

samples/client/echo_api/r/R/default_value.R

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ DefaultValue <- R6::R6Class(
119119
DefaultValueObject <- list()
120120
if (!is.null(self$`array_string_enum_ref_default`)) {
121121
DefaultValueObject[["array_string_enum_ref_default"]] <-
122-
lapply(self$`array_string_enum_ref_default`, function(x) x$toSimpleType())
122+
self$extractSimpleType(self$`array_string_enum_ref_default`)
123123
}
124124
if (!is.null(self$`array_string_enum_default`)) {
125125
DefaultValueObject[["array_string_enum_default"]] <-
@@ -152,6 +152,29 @@ DefaultValue <- R6::R6Class(
152152
return(DefaultValueObject)
153153
},
154154

155+
extractSimpleType = function(x) {
156+
if (R6::is.R6(x)) {
157+
return(x$toSimpleType())
158+
} else if (!self$hasNestedR6(x)) {
159+
return(x)
160+
}
161+
lapply(x, self$extractSimpleType)
162+
},
163+
164+
hasNestedR6 = function(x) {
165+
if (R6::is.R6(x)) {
166+
return(TRUE)
167+
}
168+
if (is.list(x)) {
169+
for (item in x) {
170+
if (self$hasNestedR6(item)) {
171+
return(TRUE)
172+
}
173+
}
174+
}
175+
FALSE
176+
},
177+
155178
#' @description
156179
#' Deserialize JSON string into an instance of DefaultValue
157180
#'

samples/client/echo_api/r/R/pet.R

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,15 @@ Pet <- R6::R6Class(
115115
}
116116
if (!is.null(self$`category`)) {
117117
PetObject[["category"]] <-
118-
self$`category`$toSimpleType()
118+
self$extractSimpleType(self$`category`)
119119
}
120120
if (!is.null(self$`photoUrls`)) {
121121
PetObject[["photoUrls"]] <-
122122
self$`photoUrls`
123123
}
124124
if (!is.null(self$`tags`)) {
125125
PetObject[["tags"]] <-
126-
lapply(self$`tags`, function(x) x$toSimpleType())
126+
self$extractSimpleType(self$`tags`)
127127
}
128128
if (!is.null(self$`status`)) {
129129
PetObject[["status"]] <-
@@ -132,6 +132,29 @@ Pet <- R6::R6Class(
132132
return(PetObject)
133133
},
134134

135+
extractSimpleType = function(x) {
136+
if (R6::is.R6(x)) {
137+
return(x$toSimpleType())
138+
} else if (!self$hasNestedR6(x)) {
139+
return(x)
140+
}
141+
lapply(x, self$extractSimpleType)
142+
},
143+
144+
hasNestedR6 = function(x) {
145+
if (R6::is.R6(x)) {
146+
return(TRUE)
147+
}
148+
if (is.list(x)) {
149+
for (item in x) {
150+
if (self$hasNestedR6(item)) {
151+
return(TRUE)
152+
}
153+
}
154+
}
155+
FALSE
156+
},
157+
135158
#' @description
136159
#' Deserialize JSON string into an instance of Pet
137160
#'

samples/client/petstore/R-httr2-wrapper/R/nested_one_of.R

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ NestedOneOf <- R6::R6Class(
8484
}
8585
if (!is.null(self$`nested_pig`)) {
8686
NestedOneOfObject[["nested_pig"]] <-
87-
self$`nested_pig`$toSimpleType()
87+
self$extractSimpleType(self$`nested_pig`)
8888
}
8989
for (key in names(self$additional_properties)) {
9090
NestedOneOfObject[[key]] <- self$additional_properties[[key]]
@@ -93,6 +93,29 @@ NestedOneOf <- R6::R6Class(
9393
return(NestedOneOfObject)
9494
},
9595

96+
extractSimpleType = function(x) {
97+
if (R6::is.R6(x)) {
98+
return(x$toSimpleType())
99+
} else if (!self$hasNestedR6(x)) {
100+
return(x)
101+
}
102+
lapply(x, self$extractSimpleType)
103+
},
104+
105+
hasNestedR6 = function(x) {
106+
if (R6::is.R6(x)) {
107+
return(TRUE)
108+
}
109+
if (is.list(x)) {
110+
for (item in x) {
111+
if (self$hasNestedR6(item)) {
112+
return(TRUE)
113+
}
114+
}
115+
}
116+
FALSE
117+
},
118+
96119
#' @description
97120
#' Deserialize JSON string into an instance of NestedOneOf
98121
#'

samples/client/petstore/R-httr2-wrapper/R/pet.R

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ Pet <- R6::R6Class(
121121
}
122122
if (!is.null(self$`category`)) {
123123
PetObject[["category"]] <-
124-
self$`category`$toSimpleType()
124+
self$extractSimpleType(self$`category`)
125125
}
126126
if (!is.null(self$`name`)) {
127127
PetObject[["name"]] <-
@@ -133,7 +133,7 @@ Pet <- R6::R6Class(
133133
}
134134
if (!is.null(self$`tags`)) {
135135
PetObject[["tags"]] <-
136-
lapply(self$`tags`, function(x) x$toSimpleType())
136+
self$extractSimpleType(self$`tags`)
137137
}
138138
if (!is.null(self$`status`)) {
139139
PetObject[["status"]] <-
@@ -146,6 +146,29 @@ Pet <- R6::R6Class(
146146
return(PetObject)
147147
},
148148

149+
extractSimpleType = function(x) {
150+
if (R6::is.R6(x)) {
151+
return(x$toSimpleType())
152+
} else if (!self$hasNestedR6(x)) {
153+
return(x)
154+
}
155+
lapply(x, self$extractSimpleType)
156+
},
157+
158+
hasNestedR6 = function(x) {
159+
if (R6::is.R6(x)) {
160+
return(TRUE)
161+
}
162+
if (is.list(x)) {
163+
for (item in x) {
164+
if (self$hasNestedR6(item)) {
165+
return(TRUE)
166+
}
167+
}
168+
}
169+
FALSE
170+
},
171+
149172
#' @description
150173
#' Deserialize JSON string into an instance of Pet
151174
#'

samples/client/petstore/R-httr2-wrapper/R/update_pet_request.R

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ UpdatePetRequest <- R6::R6Class(
7777
UpdatePetRequestObject <- list()
7878
if (!is.null(self$`jsonData`)) {
7979
UpdatePetRequestObject[["jsonData"]] <-
80-
self$`jsonData`$toSimpleType()
80+
self$extractSimpleType(self$`jsonData`)
8181
}
8282
if (!is.null(self$`binaryDataN2Information`)) {
8383
UpdatePetRequestObject[["binaryDataN2Information"]] <-
@@ -90,6 +90,29 @@ UpdatePetRequest <- R6::R6Class(
9090
return(UpdatePetRequestObject)
9191
},
9292

93+
extractSimpleType = function(x) {
94+
if (R6::is.R6(x)) {
95+
return(x$toSimpleType())
96+
} else if (!self$hasNestedR6(x)) {
97+
return(x)
98+
}
99+
lapply(x, self$extractSimpleType)
100+
},
101+
102+
hasNestedR6 = function(x) {
103+
if (R6::is.R6(x)) {
104+
return(TRUE)
105+
}
106+
if (is.list(x)) {
107+
for (item in x) {
108+
if (self$hasNestedR6(item)) {
109+
return(TRUE)
110+
}
111+
}
112+
}
113+
FALSE
114+
},
115+
93116
#' @description
94117
#' Deserialize JSON string into an instance of UpdatePetRequest
95118
#'

samples/client/petstore/R-httr2/R/nested_one_of.R

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,34 @@ NestedOneOf <- R6::R6Class(
7474
}
7575
if (!is.null(self$`nested_pig`)) {
7676
NestedOneOfObject[["nested_pig"]] <-
77-
self$`nested_pig`$toSimpleType()
77+
self$extractSimpleType(self$`nested_pig`)
7878
}
7979
return(NestedOneOfObject)
8080
},
8181

82+
extractSimpleType = function(x) {
83+
if (R6::is.R6(x)) {
84+
return(x$toSimpleType())
85+
} else if (!self$hasNestedR6(x)) {
86+
return(x)
87+
}
88+
lapply(x, self$extractSimpleType)
89+
},
90+
91+
hasNestedR6 = function(x) {
92+
if (R6::is.R6(x)) {
93+
return(TRUE)
94+
}
95+
if (is.list(x)) {
96+
for (item in x) {
97+
if (self$hasNestedR6(item)) {
98+
return(TRUE)
99+
}
100+
}
101+
}
102+
FALSE
103+
},
104+
82105
#' @description
83106
#' Deserialize JSON string into an instance of NestedOneOf
84107
#'

samples/client/petstore/R-httr2/R/pet.R

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ Pet <- R6::R6Class(
111111
}
112112
if (!is.null(self$`category`)) {
113113
PetObject[["category"]] <-
114-
self$`category`$toSimpleType()
114+
self$extractSimpleType(self$`category`)
115115
}
116116
if (!is.null(self$`name`)) {
117117
PetObject[["name"]] <-
@@ -123,7 +123,7 @@ Pet <- R6::R6Class(
123123
}
124124
if (!is.null(self$`tags`)) {
125125
PetObject[["tags"]] <-
126-
lapply(self$`tags`, function(x) x$toSimpleType())
126+
self$extractSimpleType(self$`tags`)
127127
}
128128
if (!is.null(self$`status`)) {
129129
PetObject[["status"]] <-
@@ -132,6 +132,29 @@ Pet <- R6::R6Class(
132132
return(PetObject)
133133
},
134134

135+
extractSimpleType = function(x) {
136+
if (R6::is.R6(x)) {
137+
return(x$toSimpleType())
138+
} else if (!self$hasNestedR6(x)) {
139+
return(x)
140+
}
141+
lapply(x, self$extractSimpleType)
142+
},
143+
144+
hasNestedR6 = function(x) {
145+
if (R6::is.R6(x)) {
146+
return(TRUE)
147+
}
148+
if (is.list(x)) {
149+
for (item in x) {
150+
if (self$hasNestedR6(item)) {
151+
return(TRUE)
152+
}
153+
}
154+
}
155+
FALSE
156+
},
157+
135158
#' @description
136159
#' Deserialize JSON string into an instance of Pet
137160
#'

0 commit comments

Comments
 (0)