forked from loafle/openapi-generator-original
[Scala][sttp] various bug fixes (#12254)
* avoid using deprecated enum naming * map anytype to any for sttp * circe codecs and enum fixes * regenerated the samples
This commit is contained in:
parent
1e48c95d48
commit
bee9c79e5a
@ -113,6 +113,10 @@ public class ScalaSttpClientCodegen extends AbstractScalaCodegen implements Code
|
|||||||
apiTemplateFiles.put("api.mustache", ".scala");
|
apiTemplateFiles.put("api.mustache", ".scala");
|
||||||
embeddedTemplateDir = templateDir = "scala-sttp";
|
embeddedTemplateDir = templateDir = "scala-sttp";
|
||||||
|
|
||||||
|
String jsonLibrary = JSON_LIBRARY_PROPERTY.getValue(additionalProperties);
|
||||||
|
|
||||||
|
String jsonValueClass = jsonLibrary == "circe" ? "io.circe.Json" : "org.json4s.JValue";
|
||||||
|
|
||||||
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
|
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
|
||||||
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
|
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
|
||||||
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
|
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
|
||||||
@ -148,6 +152,7 @@ public class ScalaSttpClientCodegen extends AbstractScalaCodegen implements Code
|
|||||||
typeMapping.put("number", "Double");
|
typeMapping.put("number", "Double");
|
||||||
typeMapping.put("decimal", "BigDecimal");
|
typeMapping.put("decimal", "BigDecimal");
|
||||||
typeMapping.put("ByteArray", "Array[Byte]");
|
typeMapping.put("ByteArray", "Array[Byte]");
|
||||||
|
typeMapping.put("AnyType", jsonValueClass);
|
||||||
|
|
||||||
instantiationTypes.put("array", "ListBuffer");
|
instantiationTypes.put("array", "ListBuffer");
|
||||||
instantiationTypes.put("map", "Map");
|
instantiationTypes.put("map", "Map");
|
||||||
@ -170,6 +175,7 @@ public class ScalaSttpClientCodegen extends AbstractScalaCodegen implements Code
|
|||||||
supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt"));
|
supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt"));
|
||||||
final String invokerFolder = (sourceFolder + File.separator + invokerPackage).replace(".", File.separator);
|
final String invokerFolder = (sourceFolder + File.separator + invokerPackage).replace(".", File.separator);
|
||||||
supportingFiles.add(new SupportingFile("jsonSupport.mustache", invokerFolder, "JsonSupport.scala"));
|
supportingFiles.add(new SupportingFile("jsonSupport.mustache", invokerFolder, "JsonSupport.scala"));
|
||||||
|
supportingFiles.add(new SupportingFile("additionalTypeSerializers.mustache", invokerFolder, "AdditionalTypeSerializers.scala"));
|
||||||
supportingFiles.add(new SupportingFile("project/build.properties.mustache", "project", "build.properties"));
|
supportingFiles.add(new SupportingFile("project/build.properties.mustache", "project", "build.properties"));
|
||||||
supportingFiles.add(new SupportingFile("dateSerializers.mustache", invokerFolder, "DateSerializers.scala"));
|
supportingFiles.add(new SupportingFile("dateSerializers.mustache", invokerFolder, "DateSerializers.scala"));
|
||||||
}
|
}
|
||||||
|
45
modules/openapi-generator/src/main/resources/scala-sttp/additionalTypeSerializers.mustache
vendored
Normal file
45
modules/openapi-generator/src/main/resources/scala-sttp/additionalTypeSerializers.mustache
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package {{invokerPackage}}
|
||||||
|
|
||||||
|
import java.net.{ URI, URISyntaxException }
|
||||||
|
|
||||||
|
{{#json4s}}
|
||||||
|
object AdditionalTypeSerializers {
|
||||||
|
import org.json4s.{Serializer, CustomSerializer, JNull, MappingException}
|
||||||
|
import org.json4s.JsonAST.JString
|
||||||
|
case object URISerializer extends CustomSerializer[URI]( _ => ( {
|
||||||
|
case JString(s) =>
|
||||||
|
try new URI(s)
|
||||||
|
catch {
|
||||||
|
case _: URISyntaxException =>
|
||||||
|
throw new MappingException("String could not be parsed as a URI reference, it violates RFC 2396.")
|
||||||
|
case _: NullPointerException =>
|
||||||
|
throw new MappingException("String is null.")
|
||||||
|
}
|
||||||
|
case JNull => null
|
||||||
|
}, {
|
||||||
|
case uri: URI =>
|
||||||
|
JString(uri.toString())
|
||||||
|
}))
|
||||||
|
|
||||||
|
def all: Seq[Serializer[_]] = Seq[Serializer[_]]() :+ URISerializer
|
||||||
|
}
|
||||||
|
{{/json4s}}
|
||||||
|
{{#circe}}
|
||||||
|
trait AdditionalTypeSerializers {
|
||||||
|
import io.circe._
|
||||||
|
|
||||||
|
implicit final lazy val URIDecoder: Decoder[URI] = Decoder.decodeString.emap(string =>
|
||||||
|
try Right(new URI(string))
|
||||||
|
catch {
|
||||||
|
case _: URISyntaxException =>
|
||||||
|
Left("String could not be parsed as a URI reference, it violates RFC 2396.")
|
||||||
|
case _: NullPointerException =>
|
||||||
|
Left("String is null.")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
implicit final lazy val URIEncoder: Encoder[URI] = new Encoder[URI] {
|
||||||
|
final def apply(a: URI): Json = Json.fromString(a.toString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{/circe}}
|
@ -1,9 +1,8 @@
|
|||||||
package {{invokerPackage}}
|
package {{invokerPackage}}
|
||||||
|
|
||||||
{{#java8}}
|
{{#java8}}
|
||||||
import java.time.{LocalDate, LocalDateTime, OffsetDateTime, ZoneId}
|
import java.time.{LocalDate, OffsetDateTime}
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
import scala.util.Try
|
|
||||||
{{/java8}}
|
{{/java8}}
|
||||||
{{#joda}}
|
{{#joda}}
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
@ -15,6 +14,9 @@ object DateSerializers {
|
|||||||
import org.json4s.{Serializer, CustomSerializer, JNull}
|
import org.json4s.{Serializer, CustomSerializer, JNull}
|
||||||
import org.json4s.JsonAST.JString
|
import org.json4s.JsonAST.JString
|
||||||
{{#java8}}
|
{{#java8}}
|
||||||
|
import scala.util.Try
|
||||||
|
import java.time.{LocalDateTime, ZoneId}
|
||||||
|
|
||||||
case object DateTimeSerializer extends CustomSerializer[OffsetDateTime](_ => ( {
|
case object DateTimeSerializer extends CustomSerializer[OffsetDateTime](_ => ( {
|
||||||
case JString(s) =>
|
case JString(s) =>
|
||||||
Try(OffsetDateTime.parse(s, DateTimeFormatter.ISO_OFFSET_DATE_TIME)) orElse
|
Try(OffsetDateTime.parse(s, DateTimeFormatter.ISO_OFFSET_DATE_TIME)) orElse
|
||||||
|
@ -10,23 +10,23 @@ import sttp.client3.json4s.SttpJson4sApi
|
|||||||
import scala.reflect.ClassTag
|
import scala.reflect.ClassTag
|
||||||
|
|
||||||
object JsonSupport extends SttpJson4sApi {
|
object JsonSupport extends SttpJson4sApi {
|
||||||
def enumSerializers: Seq[Serializer[_]] = Seq[Serializer[_]](){{#models}}{{#model}}{{#hasEnums}}{{#vars}}{{#isEnum}} :+
|
def enumSerializers: Seq[Serializer[_]] = Seq[Serializer[_]](){{#models}}{{#model}}{{#isEnum}} :+
|
||||||
new EnumNameSerializer({{classname}}Enums.{{datatypeWithEnum}}){{/isEnum}}{{/vars}}{{/hasEnums}}{{/model}}{{/models}}
|
new EnumNameSerializer({{classname}}){{/isEnum}}{{/model}}{{/models}}
|
||||||
|
|
||||||
private class EnumNameSerializer[E <: Enumeration: ClassTag](enum: E) extends Serializer[E#Value] {
|
private class EnumNameSerializer[E <: Enumeration: ClassTag](enumeration: E) extends Serializer[E#Value] {
|
||||||
import JsonDSL._
|
import JsonDSL._
|
||||||
val EnumerationClass: Class[E#Value] = classOf[E#Value]
|
val EnumerationClass: Class[E#Value] = classOf[E#Value]
|
||||||
|
|
||||||
def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), E#Value] = {
|
def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), E#Value] = {
|
||||||
case (t @ TypeInfo(EnumerationClass, _), json) if isValid(json) =>
|
case (t @ TypeInfo(EnumerationClass, _), json) if isValid(json) =>
|
||||||
json match {
|
json match {
|
||||||
case JString(value) => enum.withName(value)
|
case JString(value) => enumeration.withName(value)
|
||||||
case value => throw new MappingException(s"Can't convert $value to $EnumerationClass")
|
case value => throw new MappingException(s"Can't convert $value to $EnumerationClass")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private[this] def isValid(json: JValue) = json match {
|
private[this] def isValid(json: JValue) = json match {
|
||||||
case JString(value) if enum.values.exists(_.toString == value) => true
|
case JString(value) if enumeration.values.exists(_.toString == value) => true
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ object JsonSupport extends SttpJson4sApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
implicit val format: Formats = DefaultFormats ++ enumSerializers ++ DateSerializers.all
|
implicit val format: Formats = DefaultFormats ++ enumSerializers ++ DateSerializers.all ++ AdditionalTypeSerializers.all
|
||||||
implicit val serialization: org.json4s.Serialization = org.json4s.jackson.Serialization
|
implicit val serialization: org.json4s.Serialization = org.json4s.jackson.Serialization
|
||||||
}
|
}
|
||||||
{{/json4s}}
|
{{/json4s}}
|
||||||
@ -44,10 +44,15 @@ import io.circe.{Decoder, Encoder}
|
|||||||
import io.circe.generic.AutoDerivation
|
import io.circe.generic.AutoDerivation
|
||||||
import sttp.client3.circe.SttpCirceApi
|
import sttp.client3.circe.SttpCirceApi
|
||||||
|
|
||||||
object JsonSupport extends SttpCirceApi with AutoDerivation with DateSerializers {
|
object JsonSupport extends SttpCirceApi with AutoDerivation with DateSerializers with AdditionalTypeSerializers {
|
||||||
{{#models}}{{#model}}{{#hasEnums}}{{#vars}}{{#isEnum}}
|
|
||||||
implicit val {{classname}}{{datatypeWithEnum}}Decoder: Decoder[{{classname}}Enums.{{datatypeWithEnum}}] = Decoder.decodeEnumeration({{classname}}Enums.{{datatypeWithEnum}})
|
{{#models}}
|
||||||
implicit val {{classname}}{{datatypeWithEnum}}Encoder: Encoder[{{classname}}Enums.{{datatypeWithEnum}}] = Encoder.encodeEnumeration({{classname}}Enums.{{datatypeWithEnum}})
|
{{#model}}
|
||||||
{{/isEnum}}{{/vars}}{{/hasEnums}}{{/model}}{{/models}}
|
{{#isEnum}}
|
||||||
|
implicit val {{classname}}Decoder: Decoder[{{classname}}.{{classname}}] = Decoder.decodeEnumeration({{classname}})
|
||||||
|
implicit val {{classname}}Encoder: Encoder[{{classname}}.{{classname}}] = Encoder.encodeEnumeration({{classname}})
|
||||||
|
{{/isEnum}}
|
||||||
|
{{/model}}
|
||||||
|
{{/models}}
|
||||||
}
|
}
|
||||||
{{/circe}}
|
{{/circe}}
|
||||||
|
@ -4,6 +4,7 @@ project/build.properties
|
|||||||
src/main/scala/org/openapitools/client/api/PetApi.scala
|
src/main/scala/org/openapitools/client/api/PetApi.scala
|
||||||
src/main/scala/org/openapitools/client/api/StoreApi.scala
|
src/main/scala/org/openapitools/client/api/StoreApi.scala
|
||||||
src/main/scala/org/openapitools/client/api/UserApi.scala
|
src/main/scala/org/openapitools/client/api/UserApi.scala
|
||||||
|
src/main/scala/org/openapitools/client/core/AdditionalTypeSerializers.scala
|
||||||
src/main/scala/org/openapitools/client/core/DateSerializers.scala
|
src/main/scala/org/openapitools/client/core/DateSerializers.scala
|
||||||
src/main/scala/org/openapitools/client/core/JsonSupport.scala
|
src/main/scala/org/openapitools/client/core/JsonSupport.scala
|
||||||
src/main/scala/org/openapitools/client/model/ApiResponse.scala
|
src/main/scala/org/openapitools/client/model/ApiResponse.scala
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package org.openapitools.client.core
|
||||||
|
|
||||||
|
import java.net.{ URI, URISyntaxException }
|
||||||
|
|
||||||
|
object AdditionalTypeSerializers {
|
||||||
|
import org.json4s.{Serializer, CustomSerializer, JNull, MappingException}
|
||||||
|
import org.json4s.JsonAST.JString
|
||||||
|
case object URISerializer extends CustomSerializer[URI]( _ => ( {
|
||||||
|
case JString(s) =>
|
||||||
|
try new URI(s)
|
||||||
|
catch {
|
||||||
|
case _: URISyntaxException =>
|
||||||
|
throw new MappingException("String could not be parsed as a URI reference, it violates RFC 2396.")
|
||||||
|
case _: NullPointerException =>
|
||||||
|
throw new MappingException("String is null.")
|
||||||
|
}
|
||||||
|
case JNull => null
|
||||||
|
}, {
|
||||||
|
case uri: URI =>
|
||||||
|
JString(uri.toString())
|
||||||
|
}))
|
||||||
|
|
||||||
|
def all: Seq[Serializer[_]] = Seq[Serializer[_]]() :+ URISerializer
|
||||||
|
}
|
@ -1,12 +1,14 @@
|
|||||||
package org.openapitools.client.core
|
package org.openapitools.client.core
|
||||||
|
|
||||||
import java.time.{LocalDate, LocalDateTime, OffsetDateTime, ZoneId}
|
import java.time.{LocalDate, OffsetDateTime}
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
import scala.util.Try
|
|
||||||
|
|
||||||
object DateSerializers {
|
object DateSerializers {
|
||||||
import org.json4s.{Serializer, CustomSerializer, JNull}
|
import org.json4s.{Serializer, CustomSerializer, JNull}
|
||||||
import org.json4s.JsonAST.JString
|
import org.json4s.JsonAST.JString
|
||||||
|
import scala.util.Try
|
||||||
|
import java.time.{LocalDateTime, ZoneId}
|
||||||
|
|
||||||
case object DateTimeSerializer extends CustomSerializer[OffsetDateTime](_ => ( {
|
case object DateTimeSerializer extends CustomSerializer[OffsetDateTime](_ => ( {
|
||||||
case JString(s) =>
|
case JString(s) =>
|
||||||
Try(OffsetDateTime.parse(s, DateTimeFormatter.ISO_OFFSET_DATE_TIME)) orElse
|
Try(OffsetDateTime.parse(s, DateTimeFormatter.ISO_OFFSET_DATE_TIME)) orElse
|
||||||
|
@ -17,24 +17,22 @@ import sttp.client3.json4s.SttpJson4sApi
|
|||||||
import scala.reflect.ClassTag
|
import scala.reflect.ClassTag
|
||||||
|
|
||||||
object JsonSupport extends SttpJson4sApi {
|
object JsonSupport extends SttpJson4sApi {
|
||||||
def enumSerializers: Seq[Serializer[_]] = Seq[Serializer[_]]() :+
|
def enumSerializers: Seq[Serializer[_]] = Seq[Serializer[_]]()
|
||||||
new EnumNameSerializer(OrderEnums.Status) :+
|
|
||||||
new EnumNameSerializer(PetEnums.Status)
|
|
||||||
|
|
||||||
private class EnumNameSerializer[E <: Enumeration: ClassTag](enum: E) extends Serializer[E#Value] {
|
private class EnumNameSerializer[E <: Enumeration: ClassTag](enumeration: E) extends Serializer[E#Value] {
|
||||||
import JsonDSL._
|
import JsonDSL._
|
||||||
val EnumerationClass: Class[E#Value] = classOf[E#Value]
|
val EnumerationClass: Class[E#Value] = classOf[E#Value]
|
||||||
|
|
||||||
def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), E#Value] = {
|
def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), E#Value] = {
|
||||||
case (t @ TypeInfo(EnumerationClass, _), json) if isValid(json) =>
|
case (t @ TypeInfo(EnumerationClass, _), json) if isValid(json) =>
|
||||||
json match {
|
json match {
|
||||||
case JString(value) => enum.withName(value)
|
case JString(value) => enumeration.withName(value)
|
||||||
case value => throw new MappingException(s"Can't convert $value to $EnumerationClass")
|
case value => throw new MappingException(s"Can't convert $value to $EnumerationClass")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private[this] def isValid(json: JValue) = json match {
|
private[this] def isValid(json: JValue) = json match {
|
||||||
case JString(value) if enum.values.exists(_.toString == value) => true
|
case JString(value) if enumeration.values.exists(_.toString == value) => true
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,6 +41,6 @@ object JsonSupport extends SttpJson4sApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
implicit val format: Formats = DefaultFormats ++ enumSerializers ++ DateSerializers.all
|
implicit val format: Formats = DefaultFormats ++ enumSerializers ++ DateSerializers.all ++ AdditionalTypeSerializers.all
|
||||||
implicit val serialization: org.json4s.Serialization = org.json4s.jackson.Serialization
|
implicit val serialization: org.json4s.Serialization = org.json4s.jackson.Serialization
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user