目的
できるだけEncoder/Decoderを書かずに、ケースクラスをJSON化したいときは、import io.circe.generic.auto._, io.circe.syntax._
をインポートして hoge.asJson
とすればよいが、キャメルケースのフィールド名がそのままJSONに出力されてしまう。これを簡単にスネークケースにできないか? という感じでツイートしてたら教えてもらいました。それを共有します。
import io.circe._
import io.circe.syntax._
import io.circe.genric.auto._
case class UserName(firstName: String, lastName: String)
val userName = UserName(firstName = "Junichi", lastName = "Kato")
val json = userName.asJson
/*
{
"firstName": "Junichi",
"lastName": "Kato"
}
*/
implicit でconfig渡すと自動的にスネークケースになります。混在パターン駄目ですが。
— j.kugiya (@KugiyaJ) 2018年6月22日
implicit lazy val jsonConfig: Configuration =
Configuration
.default
.withSnakeCaseMemberNames
今までのやり方
最初にやってたのはこれ。タイピング数が多くなる(笑)
import io.circe._
case class UserName(firstName: String, lastName: String)
object UserName {
implicit val userNameDecoder: Decoder[UserName] = Decoder.instance{ v =>
Json.obj(
"first_name" -> v.firstName.asJson,
"last_name" -> v.lastName.asJson
)
}
}
次はforProduct??
メソッド。こっちはかなり楽になった。
import io.circe._
case class UserName(firstName: String, lastName: String)
object UserName {
implicit val userNameDecoder: Decoder[UserName] =
Decoder.forProduct2("first_name", "last_name")(UserName.apply)
}
今回の方法
circe-generic-extras
への依存関係が必要です。
libraryDependencies ++= Seq(
"io.circe" %% "circe-core",
"io.circe" %% "circe-generic",
"io.circe" %% "circe-generic-extras", // 追加
"io.circe" %% "circe-parser"
).map(_ % circeVersion)
教えてもらったとおりですが、以下のような感じでできます。
import io.circe._
import io.circe.syntax._
import io.circe.generic.extras.auto._
import io.circe.generic.extras.Configuration
case class UserName(firstName: String, lastName: String)
implicit val jsonConfig: Configuration = Configuration.default.withSnakeCaseMemberNames
val userName = UserName(firstName = "Junichi", lastName = "Kato")
val json = userName.asJson
/*
{
"first_name": "Junichi",
"last_name": "Kato"
}
*/
ケースクラスごとにConfiguration
を変えたい場合は、こんな感じでいけると思います。
import io.circe.generic.extras.semiauto._
import io.circe.generic.extras.Configuration
case class UserName(firstName: String, lastName: String)
object UserName {
implicit val jsonConfig: Configuration = Configuration.default.withSnakeCaseMemberNames
implicit val userNameDecoder: Decoder[UserName] = deriveDecoder
}