softwaremill / softwaremill/tapir

[Feature Request] codegen: do not wrap types in Option if a default is present

Open
#5,492 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Scala
Stars
1.5k
Forks
468
Avg merge
5h 37m
Merged PRs (30d)
34

Description

Hello maintainers.

This one is more of a nice to have/ improvement, and there may be a reason it was implemented this way but I am unsure why.

Currently, when generating the schema for the following object for example:

title: MyBook
properties:
  title:
    type: string
  genre:
    type: string
    default: unknown
required:
 - title

The generated case class is:

case class Book (
  title: String,
  genre: Option[String] = Some("unknown")
)

Here the genre field is marked as option, but in reality it is always set to a Some even if it is absent from the request. Handling the option later then requires to .get it, or .getOrElse with a default value, but it is already defined in the class itself !

My idea is to introduce a new parameter for generation (to avoid breaking existing generations, as an opt in behavior), named generateDefaultsAsRequired or something alike.

When this parameter is set, the above yaml would result in the following scala code:

case class Book (
  title: String,
  genre: String = "unknown"
)

The logic behind it is:

  • if param is required -> no option wrapping
  • if param has a default and is not nullable -> no option wrapping
  • all other cases -> option wrapping

I have already drafted working code on this so maybe you can have a better idea of what it could look like.

For circe, this does need to add an external dependency (which is experimental) to allow for default values to be absent from the body, hence why this is an opt-in behavior, but for the other serdes it works out of the box.

One last difference between the serdes to note is if the request contains an explicit null on a nullable field:

  • circe correctly interprets it as a None instead of the default
  • both others interpret it as the default instead

However this is not a behavior exclusive to this proposed change, and is instead the current behavior for all nullable fields if I am not mistaken.

Thank you for your time !

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked default-value-no-opt comparison, then trace the code-generation parameter and serializer handling it changes. Compare circe with the other serializers for absent defaults and explicit nulls. Done means an opt-in setting produces non-Option defaults without changing existing behavior, with coverage for the listed cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
scala
Domain
backend-api-design, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.