2017-10-17 4 views
0

は考える:封印された特性階層のためのDecodeJsonの記述?

import argonaut._ 
import Argonaut._ 
import ArgonautShapeless._ 

sealed trait Parent 
case class Foo(x: Int) extends Parent 
case class Bar(y: String) extends Parent 

を私はDecodeJson[Parent]を定義しようとしました:

implicit val parentDecodeJson: DecodeJson[Parent] = 
    DecodeJson(c => c.focus.objectFields match { 
     case Some("x" :: _) => implicitly[DecodeJson[Foo]].decode(c) 
     case _    => implicitly[DecodeJson[Bar]].decode(c) 
    }) 

しかし、argonaut.DecodeResultは不変であるので、失敗しています。動作するように思われること

implicit val parentDecodeJson: DecodeJson[Parent] = 
    DecodeJson(c => c.focus.objectFields match { 
     case Some("x" :: _) => implicitly[DecodeJson[Foo]].decode(c).flatMap{a => DecodeResult.ok(a)} 
     case _  => implicitly[DecodeJson[Bar]].decode(c).flatMap{a => DecodeResult.ok(a)} 
    }) 

<console>:42: error: type mismatch; 
found : argonaut.DecodeResult[Foo] 
required: argonaut.DecodeResult[Parent] 
Note: Foo <: Parent, but class DecodeResult is invariant in type A. 
You may wish to define A as +A instead. (SLS 4.5) 
       case Some("x" :: _) => implicitly[DecodeJson[Foo]].decode(c) 
                    ^
<console>:43: error: type mismatch; 
found : argonaut.DecodeResult[Bar] 
required: argonaut.DecodeResult[Parent] 
Note: Bar <: Parent, but class DecodeResult is invariant in type A. 
You may wish to define A as +A instead. (SLS 4.5) 
      case _  => implicitly[DecodeJson[Bar]].decode(c) 
                  ^

だから、私は思い付いた

scala> Json.obj(("x", jNumber(42))).as[Parent] 
res2: argonaut.DecodeResult[Parent] = DecodeResult(Right(Foo(42))) 

scala> Json.obj(("y", jString("hi!"))).as[Parent] 
res3: argonaut.DecodeResult[Parent] = DecodeResult(Right(Bar(hi!))) 

は、クリーンな方法はありますか?

println(EncodeJson.of[Parent].encode(Bar("a")))//{"Bar":{"y":"a"}} 
println(EncodeJson.of[Parent].apply(Bar("a")))//{"Bar":{"y":"a"}} 
println(Bar("a").asJson)//{"y":"a"} 
println((Bar("a"): Parent).asJson)//{"Bar":{"y":"a"}} 
println("{\"Bar\":{\"y\":\"a\"}}".decode[Parent])//Right(Bar(a)) 
println("{\"Bar\":{\"y\":\"a\"}}".decodeOption[Parent])//Some(Bar(a)) 

するか、私はあなたの目標を誤解しない:

+1

これは、READMEに記載されているもの(少なくともhttps://github.com/alexarchambault/argonaut-shapeless) の内容をそのまま使用してください。 –

+0

どうすればよいですか:https://stackoverflow.com/questions/39108841/json-structure-on-json-structureに基づくアルゴリズモの封印 – tkachuko

答えて

0

独自の暗黙を定義する必要はありませんか?

関連する問題