tapir icon indicating copy to clipboard operation
tapir copied to clipboard

JSON codec maps None to empty body, keeps content type

Open sangamon opened this issue 1 year ago • 0 comments

Currently, Codec#json(), used by TapirJsonCirce, will interpret an output type of Option[*] as designating an optional body: If the value is None, the response will override the underlying JSON codec's rendering to null and produce an empty body instead, which is no legal JSON, but still declare a content type of application/json.

import sttp.tapir._
import sttp.tapir.json.circe._
val codec = implicitly[Codec[String, Option[String], CodecFormat.Json]]
s"${codec.format.mediaType}: '${codec.encode(None)}'" // application/json: ''

This could either be helped by omitting the Content-type header upon empty body (and perhaps forcing a 204 status code?), or by removing the in-band signaling, i.e. encoding Option values according to the underlying codec and handling the optional body case elsewhere.

Discussion: https://softwaremill.community/t/why-map-none-to-empty-string-in-json-codec/381

sangamon avatar Mar 19 '24 12:03 sangamon