3

私はScalaで何かをしています。私は次のケースクラスを持っています:

import shapeless._
case class Foo(param1: String, param2: HList)

Circeを使用して、このタイプの JSON 表現を取得したいと思います。また、結果の JSON 文字列を型にマップし直したいと思います。

モジュール circe-shapes は、HList の自動派生を行い、HList から JSON へ、およびその逆を簡単に実行できます。次の例を参照してください。

scala> import shapeless._
import shapeless._

scala> import io.circe._, io.circe.generic.auto._, io.circe.parser._, io.circe.syntax._
import io.circe._
import io.circe.generic.auto._
import io.circe.parser._
import io.circe.syntax._

scala> import io.circe.shapes._
import io.circe.shapes._

scala> val myList = 30 :: "car" :: HNil
myList: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 30 :: car :: HNil

scala> val listJson = myList.asJson
listJson: io.circe.Json =
[
  30,
  "car"
]

scala> listJson.as[HList] // won't work
<console>:32: error: could not find implicit value for parameter d: io.circe.Decoder[shapeless.HList]
       listJson.as[HList]
                  ^

scala> listJson.as[::[Int, ::[String, HNil]]]
res3: io.circe.Decoder.Result[shapeless.::[Int,shapeless.::[String,shapeless.HNil]]] = Right(30 :: car :: HNil)

「標準」タイプを含むケース クラスも自明です。

scala> case class Bar(one: String, a: Double, andAn: Int)
defined class Bar

scala> val myBar = Bar("pie", 4.35, 2)
myBar: Bar = Bar(pie,4.35,2)

scala> val barJson = myBar.asJson
barJson: io.circe.Json =
{
  "one" : "pie",
  "a" : 4.35,
  "andAn" : 2
}

scala> barJson.as[Bar]
res5: io.circe.Decoder.Result[Bar] = Right(Bar(pie,4.35,2))

HList の型を明示的に指定すると驚くほどうまくいきますが、HList の目的が少し損なわれます。

scala> case class Foo2(a: String, b: ::[Int, ::[String, HNil]])
defined class Foo2

scala> val myFoo2 = Foo2("ark", 42 :: "meg" :: HNil)
myFoo2: Foo2 = Foo2(ark,42 :: meg :: HNil)

scala> val foo2Json = myFoo2.asJson
foo2Json: io.circe.Json =
{
  "a" : "ark",
  "b" : [
    42,
    "meg"
  ]
}

scala> foo2Json.as[Foo2]
res8: io.circe.Decoder.Result[Foo2] = Right(Foo2(ark,42 :: meg :: HNil))

Circe は任意の HList をデコードできますか?

4

1 に答える 1

5

はい、circe はこれを行うことができますが、ケース クラスを変更して、 に関する詳細情報を保持する必要がありますHList

import shapeless._

case class Foo[L <: HList](param1: String, param2: L)

そしてインポート:

import io.circe.generic.auto._, io.circe.shapes._, io.circe.parser._, io.circe.syntax._

そしてasJson、などを呼び出すことができます:

scala> val foo = Foo("ark", 42 :: "meg" :: HNil)
foo: Foo[shapeless.::[Int,shapeless.::[String,shapeless.HNil]]] = Foo(ark,42 :: meg :: HNil)

scala> foo.asJson
res0: io.circe.Json =
{
  "param1" : "ark",
  "param2" : [
    42,
    "meg"
  ]
}

scala> decode[Foo[Int :: String :: HNil]](res0.noSpaces).right.foreach(println)
Foo(ark,42 :: meg :: HNil)

この場合、具体的には、サークルの派生メカニズムは、エンコーダーとデコーダーを生成するために hlist の要素に関する静的情報を必要としますが、より一般的には、hlist を使用する場合、メンバーまたは値を普通の古いHList

タイプのものでできることはあまりありませんHList。先頭に値を追加したり、 を介して文字列表現を取得したりできますが、toStringそれだけです。Shapeless のops型クラスを使用することはできず、個々の型に関する情報を復元することはできません。常に (おそらく常に常に) が必要L <: HListです。これにより、型を有用にする情報を保持できます。

于 2016-11-28T20:40:30.973 に答える