使用Circe的AnyVal类型的通用推导

Muk*_*uki 6 json scala circe

我想为值类派生Encoder实例.使用该semiauto机制,我无法派生嵌套类.

映像以下案例类结构

{
  case class Recipient(email: Recipient.Email, name: Recipient.Name) 

  object Recipient {
     case class Email(value: String) extends AnyVal
     case class Name(value: String) extends AnyVal
  }
}
Run Code Online (Sandbox Code Playgroud)

在一个菊石壳(也添加收件人案例类)

load.ivy("io.circe" %% "circe-core" % "0.6.1")
load.ivy("io.circe" %% "circe-generic" % "0.6.1")

import io.circe._
import io.circe.generic.semiauto._
import io.circe.syntax._ 
Run Code Online (Sandbox Code Playgroud)

现在Email为预期的结果导出解码器

Recipient.Email("ab@cd.com").asJson(deriveEncoder[Recipient.Email]) 
Json = {
  "value" : "ab@cd.com"
}
Run Code Online (Sandbox Code Playgroud)

派生Encoder[Recipient]不起作用

deriveDecoder[Recipient]

could not find Lazy implicit value of type 
io.circe.generic.decoding.DerivedDecoder[$sess.cmd5.Recipient]
Run Code Online (Sandbox Code Playgroud)

我想做的是派生一个Encoder[Recipient.Email]返回包装类型.如果我明确地派生出编解码器,这个小部分就可以工作了.

import shapeless.Unwrapped

implicit def encodeAnyVal[W <: AnyVal, U](
        implicit unwrapped: Unwrapped.Aux[W, U],
                 encoderUnwrapped: Encoder[U]): Encoder[W] = {
        Encoder.instance[W](v => encoderUnwrapped(unwrapped.unwrap(v)))
}

Recipient.Email("ab@cd.com").asJson(encodeAnyVal[Recipient.Email, String])
res11: Json = "ab@cd.com"
Run Code Online (Sandbox Code Playgroud)

我仍然无法得出一个 Encoder[Recipient]

implicit val emailEncoder: Encoder[Recipient.Email] = encodeAnyVal[Recipient.Email, String] 
implicit val nameEncoder: Encoder[Recipient.Name] = encodeAnyVal[Recipient.Name, String]

deriveDecoder[Recipient] 
cmd14.sc:1: could not find Lazy implicit value of type io.circe.generic.decoding.DerivedDecoder[$sess.cmd5.Recipient]
Run Code Online (Sandbox Code Playgroud)

有没有人做过类似的事情?

提前谢谢,Muki

小智 3

您应该添加隐式见证实例而不是类型绑定。最终会得到这样的结果:

implicit def encodeAnyVal[W, U](
        implicit ev: W <:< Anyval,
                 unwrapped: Unwrapped.Aux[W, U],
                 encoderUnwrapped: Encoder[U]): Encoder[W] = {
        Encoder.instance[W](v => encoderUnwrapped(unwrapped.unwrap(v)))
}
Run Code Online (Sandbox Code Playgroud)