4

circeorを使用してargonaut、どのように書くことができますかJson => A(注 -Json型の名前ではないかもしれません) whereASSNクラスによって与えられます:

  // A USA Social Security Number has exactly 8 digits.
  case class SSN(value: Sized[List[Nat], _8])

?

擬似コード:

// assuming this function is named f

f(JsArray(JsNumber(1)))Aサイズが 1 であるため、にはなりませんが、

f(JsArray(JsNumber(1), ..., JsNumber(8)))===SSN(SizedList(1,...,8))

4

1 に答える 1

5

circe は (現在) のインスタンスを提供していませんSizedが、おそらくそうすべきです。いずれにせよ、あなたは非常に簡単に自分自身を書くことができます:

import cats.data.Xor
import io.circe.{ Decoder, DecodingFailure }
import shapeless.{ Nat, Sized }
import shapeless.ops.nat.ToInt
import shapeless.syntax.sized._

implicit def decodeSized[L <: Nat, A](implicit
  dl: Decoder[List[A]],
  ti: ToInt[L]
): Decoder[Sized[List[A], L]] = Decoder.instance { c =>
  dl(c).flatMap(as =>
    Xor.fromOption(as.sized[L], DecodingFailure(s"Sized[List[A], _${ti()}]", c.history))
  )
}

これをList表現に制限しましたが、必要に応じてより一般的にすることもできます。

これで、インスタンスを次のように記述できます(個々の数値の代わりにSSN使用していることに注意してください。静的に型付けされたものを取得すると、あまり価値がないためです)。IntNatNat

case class SSN(value: Sized[List[Int], Nat._8])

implicit val decodeSSN: Decoder[SSN] = Decoder[Sized[List[Int], Nat._8]].map(SSN(_))

その後:

scala> import io.circe.jawn.decode
import io.circe.jawn.decode

scala> decode[SSN]("[1, 2, 3, 4, 5, 6, 7, 8]")
res0: cats.data.Xor[io.circe.Error,SSN] = Right(SSN(List(1, 2, 3, 4, 5, 6, 7, 8)))

scala> decode[SSN]("[1, 2, 3, 4, 5, 6, 7]")
res1: cats.data.Xor[io.circe.Error,SSN] = Left(DecodingFailure(Sized[List[A], _8], List()))

あなたが本当にしたい場合は、Json => SSNこれを行うことができます:

val f: Json => SSN = Decoder[SSN].decodeJson(_).valueOr(throw _)

しかし、それは circe の慣用的な使い方ではありません。

于 2016-08-27T16:56:06.690 に答える