Skip to content

Commit 135ecbd

Browse files
fix compile errors after sttp upgrade, fix missing enum import in operations, fix file response. change serialization from Map to Seq to avoid deleting duplicate keys
1 parent 5887936 commit 135ecbd

7 files changed

Lines changed: 36 additions & 34 deletions

File tree

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,10 +430,14 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
430430
Map<String, String> item = new HashMap<>();
431431
if (isEnumClass(importPath, enumRefs)) {
432432
item.put("import", importPath.concat(".*"));
433+
Map<String, String> enumClassImport = new HashMap<>();
434+
enumClassImport.put("import", importPath);
435+
newImports.add(item);
436+
newImports.add(enumClassImport);
433437
} else {
434438
item.put("import", importPath);
439+
newImports.add(item);
435440
}
436-
newImports.add(item);
437441
}
438442
}
439443

@@ -691,7 +695,7 @@ private static class HandleDownloadLambda extends CustomLambda {
691695
@Override
692696
public String formatFragment(String fragment) {
693697
if (fragment.equals("asJson[File]")) {
694-
return "asFile(File.createTempFile(\"download\", \".tmp\")).mapLeft(errStr => DeserializationException(errStr, new Exception(errStr)))";
698+
return "asFile(File.createTempFile(\"download\", \".tmp\")).mapWithMetadata((result, metadata) => result.left.map(errStr => ResponseException.DeserializationException(errStr, new Exception(errStr), metadata)))";
695699
} else {
696700
return fragment;
697701
}

modules/openapi-generator/src/main/resources/scala-sttp4-jsoniter/api.mustache

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ class {{classname}}(baseUrl: String):
2121
{{#javadocRenderer}}
2222
{{>javadoc}}
2323
{{/javadocRenderer}}
24-
def {{operationId}}{{>methodParameters}}: sttp.client4.Request[{{#separateErrorChannel}}Either[ResponseException[String, Exception], {{>operationReturnType}}]{{/separateErrorChannel}}{{^separateErrorChannel}}{{>operationReturnType}}{{/separateErrorChannel}}] =
24+
def {{operationId}}{{>methodParameters}}: sttp.client4.Request[{{#separateErrorChannel}}Either[ResponseException[String], {{>operationReturnType}}]{{/separateErrorChannel}}{{^separateErrorChannel}}{{>operationReturnType}}{{/separateErrorChannel}}] =
2525
val requestURL =
2626
uri"$baseUrl{{{path}}}"{{#queryParams}}
27-
.addParams(FormSerializable.serialize("{{baseName}}", {{{paramName}}}{{#style}}, FormStyleFormat.{{style.toUpperCase}}{{/style}}{{^style}}, FormStyleFormat.FORM{{/style}}, {{isExplode}})){{/queryParams}}{{#isApiKey}}{{#isKeyInQuery}}
27+
.addParams(FormSerializable.serialize("{{baseName}}", {{{paramName}}}{{#style}}, FormStyleFormat.{{style.toUpperCase}}{{/style}}{{^style}}, FormStyleFormat.FORM{{/style}}, {{isExplode}}): _*){{/queryParams}}{{#isApiKey}}{{#isKeyInQuery}}
2828
.addParams("{{keyParamName}}" -> apiKey.value){{/isKeyInQuery}}{{/isApiKey}}
2929
3030
basicRequest
@@ -35,16 +35,14 @@ class {{classname}}(baseUrl: String):
3535
.auth.bearer(bearerToken){{/isBasicBearer}}{{/isBasic}}{{#isApiKey}}{{#isKeyInHeader}}
3636
.header("{{keyParamName}}", apiKey){{/isKeyInHeader}}{{#isKeyInCookie}}
3737
.cookie("{{keyParamName}}", apiKey){{/isKeyInCookie}}{{/isApiKey}}{{/authMethods}}{{#formParams.0}}{{^isMultipart}}
38-
.body(Map({{#formParams}}
39-
{{>paramFormCreation}}{{^-last}},{{/-last}}{{/formParams}}
40-
).collect {
41-
case (key, Some(value)) => key -> value.toString
42-
case (key, value) if value != None => key -> value.toString
43-
}){{/isMultipart}}{{#isMultipart}}
38+
.body({{#formParams}}
39+
{{>paramFormCreation}}{{^-last}} ++ {{/-last}}{{/formParams}},
40+
"utf-8"
41+
){{/isMultipart}}{{#isMultipart}}
4442
.multipartBody(Seq({{#formParams}}
4543
{{>paramMultipartCreation}}{{/formParams}}
4644
).flatten){{/isMultipart}}{{/formParams.0}}{{#bodyParam}}
47-
{{^isFile}}.body({{paramName}}){{/isFile}}{{#isFile}}.fileBody({{paramName}}){{/isFile}}{{/bodyParam}}
45+
{{^isFile}}.body(asJson({{paramName}})){{/isFile}}{{#isFile}}.fileBody({{paramName}}){{/isFile}}{{/bodyParam}}
4846
.response({{#separateErrorChannel}}{{^returnType}}asString.mapWithMetadata(ResponseAs.deserializeRightWithError(_ => Right(()))){{/returnType}}{{#fnHandleDownload}}{{#returnType}}asJson[{{>operationReturnType}}]{{/returnType}}{{/fnHandleDownload}}{{/separateErrorChannel}}{{^separateErrorChannel}}{{^returnType}}asString.mapWithMetadata(ResponseAs.deserializeRightWithError(_ => Right(()))).getRight{{/returnType}}{{#returnType}}asJson[{{>operationReturnType}}].getRight{{/returnType}}{{/separateErrorChannel}})
4947
5048
{{/operation}}

modules/openapi-generator/src/main/resources/scala-sttp4-jsoniter/helpers.mustache

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ object FormSerializable:
1919
obj: T,
2020
inline format: FormStyleFormat = FormStyleFormat.FORM,
2121
inline explode: Boolean = true
22-
): Map[String, String] =
22+
): Seq[(String, String)] =
2323
inline obj match
2424
case primitive: Primitive => serializePrimitive(name, primitive, format, explode)
2525
case array: Seq[Primitive] => serializeArray(name, array, format, explode)
26-
case optPrimitive: Option[Primitive] => optPrimitive.map(value => serializePrimitive(name, value, format, explode)).getOrElse(Map.empty[String, String])
27-
case optArray: Option[Seq[Primitive]] => optArray.map(serializeArray(name, _, format, explode)).getOrElse(Map.empty[String, String])
28-
case freeObj: Map[String, Primitive] => freeObj.map((key, value) => (key, value.toString))
26+
case optPrimitive: Option[Primitive] => optPrimitive.map(value => serializePrimitive(name, value, format, explode)).getOrElse(Seq.empty[(String, String)])
27+
case optArray: Option[Seq[Primitive]] => optArray.map(serializeArray(name, _, format, explode)).getOrElse(Seq.empty[(String, String)])
28+
case freeObj: Map[String, Primitive] => freeObj.map((key, value) => (key, value.toString)).toSeq
2929
case optObj: Option[t] =>
3030
inline summonInline[Mirror.Of[t]] match
3131
case mirror: Mirror.ProductOf[t] =>
@@ -34,7 +34,7 @@ object FormSerializable:
3434
optObj.map{ obj =>
3535
val keyVals = labels.zip(obj.asInstanceOf[Product].productIterator.toSeq.asInstanceOf[Seq[Primitive]]).toSeq
3636
serializeModel(name, keyVals, format, explode)
37-
}.getOrElse(Map.empty[String, String])
37+
}.getOrElse(Seq.empty[(String, String)])
3838
case _ => error("ERROR") // TODO - support for enums
3939
case obj =>
4040
inline summonInline[Mirror.Of[T]] match
@@ -47,7 +47,6 @@ object FormSerializable:
4747
serializeModel(name, keyVals, format, explode)
4848

4949

50-
5150
private inline def allLabels[T <: Tuple]: List[String] =
5251
constValueTuple[T].toList.asInstanceOf[List[String]]
5352

@@ -68,10 +67,10 @@ object FormSerializable:
6867
value: Primitive,
6968
inline format: FormStyleFormat,
7069
inline explode: Boolean
71-
): Map[String, String] = {
70+
): Seq[(String, String)] = {
7271
inline format match
7372
case FormStyleFormat.FORM =>
74-
Map(paramName -> value.toString) // for primitve values explode does not change anything
73+
Seq(paramName -> value.toString) // for primitve values explode does not change anything
7574
case FormStyleFormat.SPACEDELIMITED =>
7675
error(
7776
"FormStyleFormat.SpaceDelimited does not support primitive values"
@@ -87,37 +86,37 @@ object FormSerializable:
8786
values: Seq[Primitive],
8887
inline format: FormStyleFormat,
8988
inline explode: Boolean
90-
): Map[String, String] = {
89+
): Seq[(String, String)] = {
9190
inline format match
9291
case FormStyleFormat.FORM =>
93-
inline if explode then values.map(s => (paramName, s.toString)).toMap
94-
else Map(paramName -> values.mkString(","))
92+
inline if explode then values.map(s => (paramName, s.toString))
93+
else Seq(paramName -> values.mkString(","))
9594
case FormStyleFormat.SPACEDELIMITED =>
96-
inline if explode then values.map(s => (paramName, s.toString)).toMap
97-
else Map(paramName -> values.mkString(" ")) // Sttp will encode space as +, from https://swagger.io/docs/specification/v3_0/serialization/#query-parameters it is not clear if it should be + or %20
95+
inline if explode then values.map(s => (paramName, s.toString))
96+
else Seq(paramName -> values.mkString(" ")) // Sttp will encode space as +, from https://swagger.io/docs/specification/v3_0/serialization/#query-parameters it is not clear if it should be + or %20
9897
case FormStyleFormat.PIPEDELIMITED =>
99-
inline if explode then values.map(s => (paramName, s.toString)).toMap
100-
else Map(paramName -> values.mkString("|"))
98+
inline if explode then values.map(s => (paramName, s.toString))
99+
else Seq(paramName -> values.mkString("|"))
101100
case FormStyleFormat.DEEPOBJECT =>
102101
error("FormStyleFormat.DeepObject does not support arrays")
103102
}
104-
inline def serializeModel(
103+
private inline def serializeModel(
105104
paramName: String,
106105
keyValPairs: Seq[(String, Primitive)],
107106
inline format: FormStyleFormat,
108107
inline explode: Boolean
109-
): Map[String, String] = {
108+
): Seq[(String, String)] = {
110109
inline format match
111110
case FormStyleFormat.FORM =>
112-
inline if explode then keyValPairs.map((key, value) => (key, value.toString)).toMap
113-
else Map(paramName -> keyValPairs.flatMap((key,value) => Seq(key, value.toString)).mkString(","))
111+
inline if explode then keyValPairs.map((key, value) => (key, value.toString))
112+
else Seq(paramName -> keyValPairs.flatMap((key,value) => Seq(key, value.toString)).mkString(","))
114113
case FormStyleFormat.SPACEDELIMITED =>
115114
error("FormStyleFormat.SpaceDelimited does not support objects")
116115
case FormStyleFormat.PIPEDELIMITED =>
117116
error("FormStyleFormat.PipeDelimited does not support objects")
118117
case FormStyleFormat.DEEPOBJECT =>
119118
inline if explode then
120-
keyValPairs.map((key, value) => (s"$paramName[$key]", value.toString)).toMap
119+
keyValPairs.map((key, value) => (s"$paramName[$key]", value.toString))
121120
else error("FormStyleFormat.DeepObject does not support explode=false")
122121
}
123122
end FormSerializable

modules/openapi-generator/src/main/resources/scala-sttp4-jsoniter/jsonSupport.mustache

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package {{invokerPackage}}
44
{{#models.0}}
55
import {{modelPackage}}.*
66
{{/models.0}}
7+
import java.time.*
78
import com.github.plokhotnyuk.jsoniter_scala.macros.*
89
import com.github.plokhotnyuk.jsoniter_scala.core.*
910
import com.github.plokhotnyuk.jsoniter_scala.circe.JsoniterScalaCodec.*
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{{#authMethods.0}}({{#authMethods}}{{#isApiKey}}apiKey: String{{/isApiKey}}{{#isBasic}}{{#isBasicBasic}}username: String, password: String{{/isBasicBasic}}{{#isBasicBearer}}bearerToken: String{{/isBasicBearer}}{{/isBasic}}{{^-last}}, {{/-last}}{{/authMethods}}){{/authMethods.0}}{{#allParams.0}}({{#allParams}}{{paramName}}: {{#required}}{{dataType}}{{/required}}{{^required}}{{#isContainer}}{{dataType}}{{/isContainer}}{{^isContainer}}Option[{{dataType}}]{{/isContainer}}{{/required}}{{^defaultValue}}{{^required}}{{^isContainer}} = None{{/isContainer}}{{/required}}{{/defaultValue}}{{^-last}}, {{/-last}}{{/allParams}}){{/allParams.0}}
1+
{{#authMethods.0}}({{#authMethods}}{{#isApiKey}}apiKey: String{{/isApiKey}}{{#isBasic}}{{#isBasicBasic}}username: String, password: String{{/isBasicBasic}}{{#isBasicBearer}}bearerToken: String{{/isBasicBearer}}{{/isBasic}}{{^-last}}, {{/-last}}{{/authMethods}}){{/authMethods.0}}{{#allParams.0}}({{#allParams}}{{paramName}}: {{#required}}{{dataType}}{{/required}}{{^required}}{{#isContainer}}{{dataType}}{{/isContainer}}{{^isContainer}}Option[{{dataType}}]{{/isContainer}}{{/required}}{{^defaultValue}}{{^required}}{{^isContainer}} = scala.None{{/isContainer}}{{/required}}{{/defaultValue}}{{^-last}}, {{/-last}}{{/allParams}}){{/allParams.0}}

modules/openapi-generator/src/main/resources/scala-sttp4-jsoniter/model.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ case class {{classname}}(
2222
{{#description}}
2323
/* {{{.}}} */
2424
{{/description}}
25-
@named("{{baseName}}") {{{name}}}: {{^required}}Option[{{/required}}{{^isEnum}}{{dataType}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{classname}}Enums.{{datatypeWithEnum}}{{/isArray}}{{#isArray}}Seq[{{classname}}Enums.{{datatypeWithEnum}}]{{/isArray}}{{/isEnum}}{{^required}}] = None{{/required}}{{^-last}},{{/-last}}
25+
@named("{{baseName}}") {{{name}}}: {{^required}}Option[{{/required}}{{^isEnum}}{{dataType}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{classname}}Enums.{{datatypeWithEnum}}{{/isArray}}{{#isArray}}Seq[{{classname}}Enums.{{datatypeWithEnum}}]{{/isArray}}{{/isEnum}}{{^required}}] = scala.None{{/required}}{{^-last}},{{/-last}}
2626
{{/vars}}
2727
)
2828
{{/isEnum}}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"{{baseName}}" -> {{#isContainer}}FormStyleFormat.serialize({{{paramName}}}{{#collectionFormat}}, FormStyleFormat.{{style.toUpperCase}}{{/collectionFormat}}){{/isContainer}}{{^isContainer}}{{^required}}{{{paramName}}}{{/required}}{{#required}}Some({{{paramName}}}){{/required}}{{/isContainer}}
1+
FormSerializable.serialize("{{baseName}}", {{{paramName}}}{{#style}}, FormStyleFormat.{{style.toUpperCase}}{{/style}}{{^style}}, FormStyleFormat.FORM{{/style}}, {{isExplode}})

0 commit comments

Comments
 (0)