Skip to content

Commit e866657

Browse files
authored
[Fix][scala-sttp][circe] Add Base64OrArrayByteDecoder for format:byte and format:binary JSON properties (#23619)
* [Fix][scala-sttp][circe] format: byte (Base64) properties fail to deserialize - Decoder[Array[Byte]] expects JSON array * Rename decoder
1 parent 6be478d commit e866657

4 files changed

Lines changed: 20 additions & 0 deletions

File tree

modules/openapi-generator/src/main/resources/scala-sttp/additionalTypeSerializers.mustache

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ object AdditionalTypeSerializers {
2727
{{#circe}}
2828
import java.io.File
2929
import java.nio.file.Files
30+
import java.util.Base64
3031

3132
trait AdditionalTypeSerializers {
3233
import io.circe._
@@ -79,5 +80,11 @@ trait AdditionalTypeSerializers {
7980
case "-Infinity" => Right(Double.NegativeInfinity)
8081
case s => Left(s"Cannot decode '$s' as Double")
8182
})
83+
84+
implicit final lazy val Base64OrArrayByteDecoder: Decoder[Array[Byte]] =
85+
Decoder.decodeArray[Byte].or(Decoder.decodeString.emap { s =>
86+
try Right(Base64.getDecoder.decode(s))
87+
catch { case _: IllegalArgumentException => Left(s"Cannot decode '$s' as Base64 Array[Byte]") }
88+
})
8289
}
8390
{{/circe}}

modules/openapi-generator/src/test/java/org/openapitools/codegen/scala/ScalaSttpCirceCodegenTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public void verifyBaseNameFieldMapping() throws IOException {
7070
// BinaryPayload: File and untyped object fields
7171
Path binaryPath = Paths.get(outputPath + "/src/main/scala/org/openapitools/client/model/BinaryPayload.scala");
7272
assertFileContains(binaryPath, "data: Option[File]");
73+
assertFileContains(binaryPath, "checksum: Option[Array[Byte]]");
7374
assertFileContains(binaryPath, "implicit val encoderBinaryPayload");
7475
assertFileContains(binaryPath, "implicit val decoderBinaryPayload");
7576

@@ -83,6 +84,8 @@ public void verifyBaseNameFieldMapping() throws IOException {
8384
assertFileContains(serializersPath, "Double.NaN");
8485
assertFileContains(serializersPath, "Double.PositiveInfinity");
8586
assertFileContains(serializersPath, "Double.NegativeInfinity");
87+
assertFileContains(serializersPath, "Base64OrArrayByteDecoder");
88+
assertFileContains(serializersPath, "Base64.getDecoder.decode");
8689

8790
// JsonSupport should NOT use AutoDerivation
8891
Path jsonSupportPath = Paths.get(outputPath + "/src/main/scala/org/openapitools/client/core/JsonSupport.scala");

modules/openapi-generator/src/test/resources/3_0/scala/mixed-case-fields.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ components:
3434
data:
3535
type: string
3636
format: binary
37+
checksum:
38+
type: string
39+
format: byte
3740
metadata:
3841
type: object
3942
Animal:

samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/AdditionalTypeSerializers.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import java.net.{ URI, URISyntaxException }
44

55
import java.io.File
66
import java.nio.file.Files
7+
import java.util.Base64
78

89
trait AdditionalTypeSerializers {
910
import io.circe._
@@ -56,4 +57,10 @@ trait AdditionalTypeSerializers {
5657
case "-Infinity" => Right(Double.NegativeInfinity)
5758
case s => Left(s"Cannot decode '$s' as Double")
5859
})
60+
61+
implicit final lazy val Base64OrArrayByteDecoder: Decoder[Array[Byte]] =
62+
Decoder.decodeArray[Byte].or(Decoder.decodeString.emap { s =>
63+
try Right(Base64.getDecoder.decode(s))
64+
catch { case _: IllegalArgumentException => Left(s"Cannot decode '$s' as Base64 Array[Byte]") }
65+
})
5966
}

0 commit comments

Comments
 (0)