We are moving from using Jackson to Circe.
To shorten the discussion I have for example the following case class:
import com.fasterxml.jackson.databind.PropertyNamingStrategies
@JsonNaming(classOf[PropertyNamingStrategies.SnakeCaseStrategy])
final case class User(
firstName: Option[Boolean] = None,
lastName: Option[String] = None,
)
This makes sure that the external service responding with
{
"first_name": "John",
"last_name": "Doe"
}
Gets mapped properly. But I am struggling to find Circe alternative for this. I am positive there must be a built in config somewhere, I am just not reading the docs correctly
CodePudding user response:
You can use Circe Generic Extras:
final case class User(
firstName: Option[Boolean] = None,
lastName: Option[String] = None,
)
object User {
import io.circe.generic.extras.Configuration
implicit val customConfig: Configuration =
Configuration.default.withSnakeCaseMemberNames
import io.circe.generic.extras.semiauto._
implicit val encoder: Encoder[User] = deriveConfiguredEncoder
implicit val decoder: Decoder[User] = deriveConfiguredDecoder
}
In Scala 2 you could reduce some bolierplate with:
import io.circe.generic.extras.semiauto.ConfiguredJsonCodec
@ConfiguredJsonCodec
final case class User(
firstName: Option[Boolean] = None,
lastName: Option[String] = None,
)
object User {
import io.circe.generic.extras.Configuration
// this config can be put somewhere else if you want to share it
// e.g. in package object of the package - but I'd add private[packagename]
// to limit its scope to just this package
implicit val customConfig: Configuration =
Configuration.default.withSnakeCaseMemberNames
}
Unfortunately, as I am writing this, it hasn't been adjusted for Scala 3, I see no build-in derived
method in these classes, so you cannot do just
final case class User(
firstName: Option[Boolean] = None,
lastName: Option[String] = None,
) derives ConfiguredEncoder, ConfiguredDecoder
object User {
import io.circe.generic.extras.Configuration
implicit val customConfig: Configuration =
Configuration.default.withSnakeCaseMemberNames
}
But maybe it will be added in future so Scala 3 version could have as little boilerplate as Scala 2.