0Pricing
Scala for Backend Engineering & Functional Programming · レッスン

ケースクラスにデコードする

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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. JSONを解析する
  2. ケースクラスにデコードする
  3. JSONにエンコードする
  4. カスタムCodec
← Scala for Backend Engineering & Functional Programmingに戻る