diff --git a/modules/openapi-generator/src/main/resources/scala-sttp/additionalTypeSerializers.mustache b/modules/openapi-generator/src/main/resources/scala-sttp/additionalTypeSerializers.mustache index 8d97fa9e105c..12b87cec793b 100644 --- a/modules/openapi-generator/src/main/resources/scala-sttp/additionalTypeSerializers.mustache +++ b/modules/openapi-generator/src/main/resources/scala-sttp/additionalTypeSerializers.mustache @@ -27,6 +27,7 @@ object AdditionalTypeSerializers { {{#circe}} import java.io.File import java.nio.file.Files +import java.util.Base64 trait AdditionalTypeSerializers { import io.circe._ @@ -79,5 +80,11 @@ trait AdditionalTypeSerializers { case "-Infinity" => Right(Double.NegativeInfinity) case s => Left(s"Cannot decode '$s' as Double") }) + + implicit final lazy val Base64OrArrayByteDecoder: Decoder[Array[Byte]] = + Decoder.decodeArray[Byte].or(Decoder.decodeString.emap { s => + try Right(Base64.getDecoder.decode(s)) + catch { case _: IllegalArgumentException => Left(s"Cannot decode '$s' as Base64 Array[Byte]") } + }) } {{/circe}} diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/scala/ScalaSttpCirceCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/scala/ScalaSttpCirceCodegenTest.java index 9860771dcbae..b1875268f72c 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/scala/ScalaSttpCirceCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/scala/ScalaSttpCirceCodegenTest.java @@ -70,6 +70,7 @@ public void verifyBaseNameFieldMapping() throws IOException { // BinaryPayload: File and untyped object fields Path binaryPath = Paths.get(outputPath + "/src/main/scala/org/openapitools/client/model/BinaryPayload.scala"); assertFileContains(binaryPath, "data: Option[File]"); + assertFileContains(binaryPath, "checksum: Option[Array[Byte]]"); assertFileContains(binaryPath, "implicit val encoderBinaryPayload"); assertFileContains(binaryPath, "implicit val decoderBinaryPayload"); @@ -83,6 +84,8 @@ public void verifyBaseNameFieldMapping() throws IOException { assertFileContains(serializersPath, "Double.NaN"); assertFileContains(serializersPath, "Double.PositiveInfinity"); assertFileContains(serializersPath, "Double.NegativeInfinity"); + assertFileContains(serializersPath, "Base64OrArrayByteDecoder"); + assertFileContains(serializersPath, "Base64.getDecoder.decode"); // JsonSupport should NOT use AutoDerivation Path jsonSupportPath = Paths.get(outputPath + "/src/main/scala/org/openapitools/client/core/JsonSupport.scala"); diff --git a/modules/openapi-generator/src/test/resources/3_0/scala/mixed-case-fields.yaml b/modules/openapi-generator/src/test/resources/3_0/scala/mixed-case-fields.yaml index e5cdbae40845..4802cc24c3e6 100644 --- a/modules/openapi-generator/src/test/resources/3_0/scala/mixed-case-fields.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/scala/mixed-case-fields.yaml @@ -34,6 +34,9 @@ components: data: type: string format: binary + checksum: + type: string + format: byte metadata: type: object Animal: diff --git a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/AdditionalTypeSerializers.scala b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/AdditionalTypeSerializers.scala index 50a03ec77d31..2844517144b6 100644 --- a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/AdditionalTypeSerializers.scala +++ b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/AdditionalTypeSerializers.scala @@ -4,6 +4,7 @@ import java.net.{ URI, URISyntaxException } import java.io.File import java.nio.file.Files +import java.util.Base64 trait AdditionalTypeSerializers { import io.circe._ @@ -56,4 +57,10 @@ trait AdditionalTypeSerializers { case "-Infinity" => Right(Double.NegativeInfinity) case s => Left(s"Cannot decode '$s' as Double") }) + + implicit final lazy val Base64OrArrayByteDecoder: Decoder[Array[Byte]] = + Decoder.decodeArray[Byte].or(Decoder.decodeString.emap { s => + try Right(Base64.getDecoder.decode(s)) + catch { case _: IllegalArgumentException => Left(s"Cannot decode '$s' as Base64 Array[Byte]") } + }) }