You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Optional] Sponsorship to speed up the bug fix or feature
request (example)
Description
When using the scala-sttp generator with jsonLibrary=circe, the generated code relies on circe's AutoDerivation to derive Encoder/Decoder instances. This derives codecs from Scala field names (camelCase), not the original JSON property names from the OpenAPI spec.
Properties like first-name (kebab-case), phone_number (snake_case), or ZipCode (PascalCase) are converted to camelCase Scala fields (firstName, phoneNumber, zipCode). Circe's AutoDerivation then serializes/deserializes using these Scala field names instead of the original JSON names, breaking the wire contract.
Additionally, AutoDerivation cannot derive codecs for File (from format: binary) or Any (from type: object),
causing compilation failures when those types appear in model properties.
openapi-generator version
7.22.0-SNAPSHOT (latest master as of 2026-04-07), also affects 7.21.0 and all prior versions with circe support.
Note: format: binary maps to java.io.File and type: object (without properties) maps to Any in the scala-sttp generator. Circe's AutoDerivation cannot derive codecs for either type, causing compilation failures.
Generation Details
$ openapi-generator-cli version
7.22.0-SNAPSHOT
$ openapi-generator-cli generate \
-i mixed-case-fields.yaml \
-g scala-sttp \
-o /tmp/scala-sttp-circe-test \
--additional-properties=jsonLibrary=circe
[main] INFO o.o.codegen.DefaultGenerator - Generating with dryRun=false
[main] INFO o.o.codegen.DefaultGenerator - OpenAPI Generator: scala-sttp (client)
[main] INFO o.o.codegen.DefaultGenerator - Generator 'scala-sttp' is considered stable.
[main] INFO o.o.c.languages.AbstractScalaCodegen - Environment variable SCALA_POST_PROCESS_FILE not defined so the Scala code may not be properly formatted. To define it, try 'export SCALA_POST_PROCESS_FILE=/usr/local/bin/scalafmt' (Linux/Mac)
[main] INFO o.o.c.languages.AbstractScalaCodegen - NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).
[main] INFO o.o.codegen.TemplateManager - writing file /tmp/scala-sttp-circe-test/src/main/scala/org/openapitools/client/model/MixedCaseModel.scala
[main] INFO o.o.codegen.TemplateManager - writing file /tmp/scala-sttp-circe-test/src/main/scala/org/openapitools/client/api/DefaultApi.scala
[main] INFO o.o.codegen.TemplateManager - writing file /tmp/scala-sttp-circe-test/src/main/scala/org/openapitools/client/core/JsonSupport.scala
[main] INFO o.o.codegen.TemplateManager - writing file /tmp/scala-sttp-circe-test/src/main/scala/org/openapitools/client/core/AdditionalTypeSerializers.scala
Inspect the generated MixedCaseModel.scala — there is no companion object with explicit encoder/decoder. The code
relies on AutoDerivation which uses Scala field names on the wire.
AutoDerivation will ser/deserialize phoneNumber instead of the original phone_number, firstName instead of first-name, and zipCode instead of ZipCode.
Attempting to compile the generated project fails:
[error] could not find implicit value for evidence parameter of type io.circe.Encoder[java.io.File]
[error] could not find implicit value for evidence parameter of type io.circe.Encoder[Any]
The scala-http4s generator already handles this correctly by generating explicit Encoder/Decoder instances using baseName in model.mustache
The scala-sttp4-jsoniter generator handles this correctly using @named("{{baseName}}") annotations
The type: object -> Any mapping also differs: scala-http4s maps it to Json (which has built-in circe codecs),
while scala-sttp maps it to Any (which does not)
model.mustache: For circe ({{#circe}}), generate a companion object with explicit Encoder.instance/ Decoder.instance per model using {{baseName}} for JSON field names, following the scala-http4s pattern.
jsonSupport.mustache: Remove AutoDerivation mixin since explicit instances are now generated per model.
additionalTypeSerializers.mustache: Add circe Encoder/Decoder for File (delegating to Array[Byte]
codec) and Any (delegating to Json codec).
ScalaSttpClientCodegen.java: Map type: object to io.circe.Json for circe (and org.json4s.JValue for
json4s) instead of Any, matching scala-http4s.
I'm planning to submit a pull request with this fix.
Bug Report Checklist
you tested with the latest master
to confirm the issue still exists?
request (example)
Description
scala-sttpgenerator withjsonLibrary=circe, the generated code relies on circe'sAutoDerivationto deriveEncoder/Decoderinstances. This derives codecs from Scala field names (camelCase), not the original JSON property names from the OpenAPI spec.first-name(kebab-case),phone_number(snake_case), orZipCode(PascalCase) are converted to camelCase Scala fields (firstName,phoneNumber,zipCode). Circe'sAutoDerivationthen serializes/deserializes using these Scala field names instead of the original JSON names, breaking the wire contract.AutoDerivationcannot derive codecs forFile(fromformat: binary) orAny(fromtype: object),causing compilation failures when those types appear in model properties.
openapi-generator version
7.22.0-SNAPSHOT (latest master as of 2026-04-07), also affects 7.21.0 and all prior versions with circe support.
OpenAPI declaration file content or url
Note:
format: binarymaps tojava.io.Fileandtype: object(without properties) maps toAnyin the scala-sttp generator. Circe'sAutoDerivationcannot derive codecs for either type, causing compilation failures.Generation Details
$ openapi-generator-cli generate \ -i mixed-case-fields.yaml \ -g scala-sttp \ -o /tmp/scala-sttp-circe-test \ --additional-properties=jsonLibrary=circe [main] INFO o.o.codegen.DefaultGenerator - Generating with dryRun=false [main] INFO o.o.codegen.DefaultGenerator - OpenAPI Generator: scala-sttp (client) [main] INFO o.o.codegen.DefaultGenerator - Generator 'scala-sttp' is considered stable. [main] INFO o.o.c.languages.AbstractScalaCodegen - Environment variable SCALA_POST_PROCESS_FILE not defined so the Scala code may not be properly formatted. To define it, try 'export SCALA_POST_PROCESS_FILE=/usr/local/bin/scalafmt' (Linux/Mac) [main] INFO o.o.c.languages.AbstractScalaCodegen - NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI). [main] INFO o.o.codegen.TemplateManager - writing file /tmp/scala-sttp-circe-test/src/main/scala/org/openapitools/client/model/MixedCaseModel.scala [main] INFO o.o.codegen.TemplateManager - writing file /tmp/scala-sttp-circe-test/src/main/scala/org/openapitools/client/api/DefaultApi.scala [main] INFO o.o.codegen.TemplateManager - writing file /tmp/scala-sttp-circe-test/src/main/scala/org/openapitools/client/core/JsonSupport.scala [main] INFO o.o.codegen.TemplateManager - writing file /tmp/scala-sttp-circe-test/src/main/scala/org/openapitools/client/core/AdditionalTypeSerializers.scalaSteps to reproduce
mixed-case-fields.yamlMixedCaseModel.scala— there is no companion object with explicit encoder/decoder. The coderelies on
AutoDerivationwhich uses Scala field names on the wire.JsonSupport.scala:AutoDerivationwill ser/deserializephoneNumberinstead of the originalphone_number,firstNameinstead offirst-name, andzipCodeinstead ofZipCode.Actual wire behavior:
{ "firstName": "John", "phoneNumber": "555-1234", "zipCode": "90210" }Expected wire behavior (matching the spec):
{ "first-name": "John", "phone_number": "555-1234", "ZipCode": "90210" }Related issues/PRs
scala-http4sgenerator already handles this correctly by generating explicitEncoder/Decoderinstances usingbaseNameinmodel.mustachescala-sttp4-jsonitergenerator handles this correctly using@named("{{baseName}}")annotationstype: object->Anymapping also differs:scala-http4smaps it toJson(which has built-in circe codecs),while
scala-sttpmaps it toAny(which does not)Suggest a fix
model.mustache: For circe ({{#circe}}), generate a companion object with explicitEncoder.instance/Decoder.instanceper model using{{baseName}}for JSON field names, following thescala-http4spattern.jsonSupport.mustache: RemoveAutoDerivationmixin since explicit instances are now generated per model.additionalTypeSerializers.mustache: Add circeEncoder/DecoderforFile(delegating toArray[Byte]codec) and
Any(delegating toJsoncodec).ScalaSttpClientCodegen.java: Maptype: objecttoio.circe.Jsonfor circe (andorg.json4s.JValueforjson4s) instead of
Any, matchingscala-http4s.I'm planning to submit a pull request with this fix.