Кирка не (в настоящее время) обеспечивают экземпляры для 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
экземпляр, как это (обратите внимание, что я использую Int
вместо Nat
для отдельных номеров, так как только вы получили что-то статически типизированных как Nat
это не стоит):
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 _)
Но это не идиоматическое использование цирце.
https://en.wikipedia.org/wiki/Social_Security_number https://www.ssa.gov/policy/docs/ssb/v69n2/v69n2p55.html –
Ха-ха - хороший улов. 9 цифр ssn, а не 8. –