2017-06-30 5 views
0

implicitスコープのmodels.AccountStatusにはplay.api.libs.json.Formatのインスタンスはありません。暗黙のスコープ内のmodels.AccountStatusにはplay.api.libs.json.Formatのインスタンスはありません

これはgithubページから取得したコードで、クラス名と変数名のみが変更されています。

package models 

import slick.jdbc.H2Profile._ 
import play.api.libs.json._ 

case class Account(id: Long, name: String, category: Int, status:AccountStatus) 

object Account { 
    implicit val accountFormat = Json.format[Account] 
} 

sealed abstract class AccountStatus(val as:Int) 

object AccountStatus{ 
    final case object Draft extends AccountStatus(0) 
    final case object Active extends AccountStatus(1) 
    final case object Blocked extends AccountStatus(2) 
    final case object Defaulter extends AccountStatus(3) 

    implicit val columnType: BaseColumnType[AccountStatus] = MappedColumnType.base[AccountStatus,Int](AccountStatus.toInt, AccountStatus.fromInt) 

    private def toInt(as:AccountStatus):Int = as match { 
    case Draft => 0 
    case Active => 1 
    case Blocked => 2 
    case Defaulter => 3 
    } 

    private def fromInt(as: Int): AccountStatus = as match { 
    case 0 => Draft 
    case 1 => Active 
    case 2 => Blocked 
    case 3 => Defaulter 
    _ => sys.error("Out of bound AccountStatus Value.") 
    } 
} 

https://github.com/playframework/play-scala-slick-example/blob/2.6.x/app/models/Person.scala

+1

暗黙の書き込みと読み取りを定義する必要があります書式)を入力してください。 – EdgeCaseBerg

+0

@EdgeCaseBergどうすればいいですか?私は全く新しいスカラーです。 –

+0

私はちょっと答えを投稿します。あなたのために何かを書きましょう。 – EdgeCaseBerg

答えて

1

我々はAccountStatusIntを変換するfromIntを使用する必要があるためので、このコードはobject AccountStatusコードブロックの内部を追加する必要があります。これは、AccountStatusのために定義されReadsです:

implicit object AccountStatusReads extends Reads[AccountStatus] { 
    def reads(jsValue: JsValue): JsResult[AccountStatus] = { 
    (jsValue \ "as").validate[Int].map(fromInt) 
    } 
} 

Reads何? JSON値をカプセル化するplayクラスであるJSValueをJSONから何らかの型に逆シリアル化する方法を定義するのはtraitです。この特性は、ある種のjsonを取り込み、何らかのタイプのJsResultを返す、1つのメソッド、readsメソッドのみを必要とします。したがって、上記のコードではReadsがあり、JSONのフィールドを検索してasと呼び、これを整数として読み取ろうとしています。そこから、すでに定義されたfromIntメソッドを使用して、AccountStatusに変換されます。だから、例えば、あなたがこれを行うことがScalaのコンソールで:

scala> Json.parse("""{"as":20}""").as[AccountStatus] 
java.lang.RuntimeException: Out of bound AccountStatus Value. 
    at scala.sys.package$.error(package.scala:27) 
    at AccountStatus$.fromInt(<console>:42) 
    at AccountStatusReads$$anonfun$reads$1.apply(<console>:27) 
    at AccountStatusReads$$anonfun$reads$1.apply(<console>:27) 
    at play.api.libs.json.JsResult$class.map(JsResult.scala:81) 
    at play.api.libs.json.JsSuccess.map(JsResult.scala:9) 
    at AccountStatusReads$.reads(<console>:27) 
    at play.api.libs.json.JsValue$class.as(JsValue.scala:65) 
    at play.api.libs.json.JsObject.as(JsValue.scala:166) 
    ... 42 elided 
を:

import play.api.libs.json._ 
// import wherever account status is and the above reader 
scala> Json.parse("""{"as":1}""").as[AccountStatus] 
res0: AccountStatus = Active 

このリーダーは、それはあなたのコードは、バインドされた番号のあなたを上与えるエラーを処理していない主な理由は、しかし完璧ではありません

これを処理するには、Readsでエラーを処理します。私はあなたが望むなら、どのようにして表示することができますが、最初にFormatの他の部分はWritesです。 This traitは、それと逆のことを除いて、驚くことはなく読み込みに似ています。あなたのクラスはAccountStatusで、JsValue(JSON)を作成しています。したがって、writesメソッドを実装するだけで済みます。これがそうのようにJSONにそのクラスをシリアル化するために使用することができ

implicit object AccountStatusWrites extends Writes[AccountStatus] { 
    def writes(as: AccountStatus): JsValue = { 
    JsObject(Seq("as" -> JsNumber(as.as))) 
    } 
} 

は次に:

scala> Json.toJson(Draft) 
res4: play.api.libs.json.JsValue = {"as":0} 

、これは実際に離れて行くためにあなたのエラーを取得するのに十分です。どうして? Json.format[Account]はすべてあなたのためにやったことがあります!しかし、アカウント。これはケースクラスで22フィールド未満のため、これを行うことができます。 Accountのすべてのフィールドには、(ReadsWritesを使用して)JSONとの間で変換する方法があります。一部のフォーム(ステータスフィールド)にフォーマッタがないため、アカウントに自動的に作成されたフォーマットを表示できないというエラーメッセージが表示されました。

あなたはにこれを行う必要がありますか? AccountStatusはケースクラスではないので、Json.format[AccountStatus]を呼び出すことはできません。また、そのサブクラスは各オブジェクトであるため、ケースクラスではないため、unapplyメソッドは定義されていません。したがって、シリアライズとデシリアライズの方法をライブラリに説明する必要があります。

あなたがスカラーを初めて使ったと言われたので、私は暗黙のコンセプトがやや外国語であると想像します。コンパイラが暗黙のうちに必要なものを見つけることができないと不満を抱いているのを見て、何をすべきかを把握するために読んでみることをお勧めします。

ラウンド

ボーナスだから、あなたは本当にそれが自分の仕事やりたくないかもしれませんし、あなたがJson.format[AccountStatus]を行うことができますので、それを行うことを避けるための方法があります。 Json.formatは、汚れた作業を行うためにapplyunapplyメソッドを使用しています。スカラーでは、これらの2つのメソッドはケースクラスに対して自動的に定義されます。しかし、自分で定義することはできませんし、無料であなたに与えるすべてのものを手に入れることはできません。

だから、applyunapplyはタイプシグネチャに似ていますか?クラスごとに変更されますが、この場合はapplyInt => AccountStatus(intからAccountStatusに移行する関数)と一致する必要があります。だから、それがそうのように定義されています:

def apply(i: Int): AccountStatus = fromInt(i) 

と適用を解除するには、この逆のに似ていますが、それはあなたが「ドン定義されたこれらの両方を持つ

def unapply(as: AccountStatus): Option[Int] = Option(as.as) 

のように見えるので、それは、Option[Int]を返す必要があります読み書きを定義する必要はなく、代わりに

// this is still inside the AccountStatus object { ... } 
implicit val asFormat = Json.format[AccountStatus] 

と呼ぶことができ、同様の方法で動作します。

.P.S。私は今日旅行していますが、これが意味をなさない場合はコメントを残しておいてください。後であなたに連絡しようとします。

+0

エラーが消えましたが、新しいエラーが発生しました: - 'slick.jdbc型の証拠パラメータの暗黙の値が見つかりませんでした.H2Profile.BaseColumnType [Int] ' –

+0

は滑らかなエラーだと私は本当にそのライブラリを頻繁に使用しないので、それをどう対処するか分からない。そのライブラリのユーザーガイドを調べることをおすすめします。 – EdgeCaseBerg

+0

ありがとうございました。すべてのエラーは解決されましたが、全体のエラーと解決策はSCALAについて多くのことを教えてくれました。 JSONシリアライズについての完全なホワイトペーパーへのリンクは、今後私にとって参考になるでしょう –

関連する問題