ケースクラスにデコードする
JSONを独自の型に対応付けます。
「ケースクラスにデコードする」はCoddyKit上の無料Scala for Backend Engineering & Functional Programmingレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはScala for Backend Engineering & Functional Programming学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Scala for Backend Engineering & Functional Programmingコースには全4レッスンが含まれています。
DecoderでJSONを型に対応付ける
Decoder[A]は、Json値をScalaの型Aとして読み取る方法を知っています。
Circeにはプリミティブ型やコレクション用のDecoderが標準で用意されており、独自のcase class用Decoderも自動的に構築できます。
対象となるCase Class
APIがユーザーのレコードを返すとします。JSONのキーと一致するフィールド名を持つcase classで、その形状をモデル化します。
名前が一致しているため、手動で接続処理を書かなくてもCirceがDecoderを導出できます。
case class User(name: String, age: Int, admin: Boolean)自動導出
io.circe.generic.auto._をインポートすると、必要な場所で必要になったときに、CirceがDecoder[User]を暗黙的に導出します。
その後は、追加の定型コードなしでdecode[User]を呼び出せます。
import io.circe.generic.auto._
import io.circe.parser.decode
val json = "{\"name\":\"Ada\",\"age\":36,\"admin\":true}"
val user = decode[User](json)
println(user) // Right(User(Ada,36,true))半自動導出
コンパイル時間を短縮し、明示的に制御したい場合は、io.circe.generic.semiauto.deriveDecoderを使用します。
通常はコンパニオンオブジェクト内でDecoderを一度定義し、その単一のインスタンスをどこでも再利用します。
import io.circe.Decoder
import io.circe.generic.semiauto._
object User {
implicit val dec: Decoder[User] = deriveDecoder[User]
}デコードの失敗
必須フィールドが存在しない場合や型が正しくない場合、デコードはDecodingFailureで失敗します。
失敗情報にはCursor操作のhistoryが含まれ、問題の原因となったフィールドを正確に特定できます。
val bad = decode[User]("{\"name\":\"Ada\"}")
println(bad)
// Left(DecodingFailure at .age: Missing required field)クラス内のオプションフィールド
JSONキーが存在しない、またはnullになる可能性がある場合は、フィールドをOption[A]にします。
Circeは存在しないキーを自動的にNoneへデコードするため、オプション性のためだけにカスタムDecoderを作る必要はありません。
case class Account(id: Long, nickname: Option[String])
val a = decode[Account]("{\"id\":7}")
println(a) // Right(Account(7,None))デフォルト値
case classのデフォルト値で、存在しないJSONキーを補完できます。ただし、デフォルト値を有効にするconfigured導出を使用した場合に限ります。
circe-generic-extrasモジュールのConfiguration.default.withDefaultsで、この機能を利用できます。
import io.circe.generic.extras._
implicit val cfg: Configuration =
Configuration.default.withDefaults
@ConfiguredJsonCodec
case class Settings(theme: String = "dark")ネストしたCase Class
デコードは合成的に機能します。Circeが各フィールドの型をデコードできれば、他のcase classをネストしたクラスもデコードできます。
導出は自動的に再帰するため、1つのインポートで深くネストした構造にも対応できます。
case class Address(city: String)
case class Person(name: String, address: Address)
val p = decode[Person](
"{\"name\":\"Ada\",\"address\":{\"city\":\"London\"}}")
println(p)フィールド名を変更する
JSONのキーとScalaの名前が異なる場合(たとえばsnake_caseの場合)は、Configuration.default.withSnakeCaseMemberNamesを使ったconfigured導出を使用します。
これにより、手書きのDecoderなしでcreated_atをScalaのフィールドcreatedAtに対応付けられます。
import io.circe.generic.extras._
implicit val cfg: Configuration =
Configuration.default.withSnakeCaseMemberNames
@ConfiguredJsonCodec
case class Event(createdAt: String)エラーを蓄積する
デフォルトでは、デコードは最初のエラーで失敗します。一方、decodeAccumulatingはすべての失敗をValidatedNelに収集します。
これは、すべての問題を一度に報告したいフォーム検証に便利です。
import io.circe.Decoder
val result = Decoder[User]
.decodeAccumulating(json.hcursor)
// Validated[NonEmptyList[DecodingFailure], User]導出方式を選ぶ
手早いプロトタイプにはautoを使用し、固定されたインスタンスと高速なコンパイルを求める本番コードにはsemiautoを使用します。
名前変更、デフォルト値、ディスクリミネータが必要な場合はgeneric-extrasを使用してください。
確認問題
case classへのデコードについて理解度を確認しましょう。
まとめ
Decoder[A]はJSONを型付きの値に変換します。キーと名前が一致するcase classには、generic.autoまたはsemiauto.deriveDecoderを使用します。
存在しないキーは、OptionフィールドではNoneにデコードされます。generic-extrasはデフォルト値と名前変更を追加し、decodeAccumulatingはすべてのエラーを収集します。
よくある質問
「ケースクラスにデコードする」レッスンは無料ですか?
はい。「ケースクラスにデコードする」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Scala for Backend Engineering & Functional Programmingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Scala for Backend Engineering & Functional Programmingコースには全4レッスンが含まれています。
「ケースクラスにデコードする」で何を学びますか?
JSONを独自の型に対応付けます。 ブラウザで直接実行するハンズオンコードでScala for Backend Engineering & Functional Programmingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Scala for Backend Engineering & Functional Programmingを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのScala for Backend Engineering & Functional Programmingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「ケースクラスにデコードする」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このScala for Backend Engineering & Functional Programmingレッスンでコードを書いて実行できますか?
はい。すべてのScala for Backend Engineering & Functional Programmingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- JSONを解析する
- ケースクラスにデコードする
- JSONにエンコードする
- カスタムCodec