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 bbac20f10325..8d97fa9e105c 100644 --- a/modules/openapi-generator/src/main/resources/scala-sttp/additionalTypeSerializers.mustache +++ b/modules/openapi-generator/src/main/resources/scala-sttp/additionalTypeSerializers.mustache @@ -71,5 +71,13 @@ trait AdditionalTypeSerializers { case s: String => Json.fromString(s) case other => Json.fromString(other.toString) } + + implicit final lazy val NanTolerantDoubleDecoder: Decoder[Double] = + Decoder.decodeDouble.or(Decoder.decodeString.emap { + case "NaN" => Right(Double.NaN) + case "Infinity" => Right(Double.PositiveInfinity) + case "-Infinity" => Right(Double.NegativeInfinity) + case s => Left(s"Cannot decode '$s' as Double") + }) } {{/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 950987bfe911..9860771dcbae 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 @@ -73,12 +73,16 @@ public void verifyBaseNameFieldMapping() throws IOException { assertFileContains(binaryPath, "implicit val encoderBinaryPayload"); assertFileContains(binaryPath, "implicit val decoderBinaryPayload"); - // AdditionalTypeSerializers: File and Any codecs + // AdditionalTypeSerializers: File, Any, and NaN-tolerant Double codecs Path serializersPath = Paths.get(outputPath + "/src/main/scala/org/openapitools/client/core/AdditionalTypeSerializers.scala"); assertFileContains(serializersPath, "FileDecoder"); assertFileContains(serializersPath, "FileEncoder"); assertFileContains(serializersPath, "AnyDecoder"); assertFileContains(serializersPath, "AnyEncoder"); + assertFileContains(serializersPath, "NanTolerantDoubleDecoder"); + assertFileContains(serializersPath, "Double.NaN"); + assertFileContains(serializersPath, "Double.PositiveInfinity"); + assertFileContains(serializersPath, "Double.NegativeInfinity"); // JsonSupport should NOT use AutoDerivation Path jsonSupportPath = Paths.get(outputPath + "/src/main/scala/org/openapitools/client/core/JsonSupport.scala"); 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 962c4a002f32..50a03ec77d31 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 @@ -48,4 +48,12 @@ trait AdditionalTypeSerializers { case s: String => Json.fromString(s) case other => Json.fromString(other.toString) } + + implicit final lazy val NanTolerantDoubleDecoder: Decoder[Double] = + Decoder.decodeDouble.or(Decoder.decodeString.emap { + case "NaN" => Right(Double.NaN) + case "Infinity" => Right(Double.PositiveInfinity) + case "-Infinity" => Right(Double.NegativeInfinity) + case s => Left(s"Cannot decode '$s' as Double") + }) }