我正在使用http4s编写一个web服务项目,每次我编写新的数据对象时,都需要编写以下代码
import argonaut.{Argonaut, CodecJson}
import org.http4s.{EntityDecoder, EntityEncoder}
import org.http4s.argonaut._
final case class Name (name: String, age : Int)
object Name {
implicit val codec : CodecJson[Name] =
Argonaut.casecodec2(Name.apply, Name.unapply)("name", "age")
implicit val decoder : EntityDecoder[Name] = jsonOf[Name]
implicit val encoder : EntityEncoder[Name] = jsonEncoderOf[Name]
}
根据case类中的字段数量,我需要使用相应的casecodeX方法(其中x是字段的数量),然后将字段列表传递给它。
你能告诉我最好的方法是什么,这样我就不用写当前在伴生对象中的代码了吗?
我的想法是,我应该写一个宏来解析Name类的代码,然后输出包含编解码器、编码器和解码器的类。但是我不知道如何继续这个宏的实现。
有没有更好的方法?
发布于 2016-09-27 12:17:38
对于编解码器,您可以使用argonaut-shapeless,特别是JsonCodec。对于编码器/解码器,您可以将jsonOf
作为decoder
传递给您要调用的函数,隐式派生将为您完成剩下的工作。遗憾的是你不能绕过jsonOf
,it has been tried。
发布于 2016-09-27 12:18:01
不确定它是否真的会更好,但你可以从编码器和解码器的通用隐含开始:
implicit def decoder[A](implicit cj: CodecJson[A]): EntityDecoder[A] = jsonOf[A]
implicit val encoder[A](implicit cj: CodecJson[A]) : EntityEncoder[A] = jsonEncoderOf[A]
在这一步上,你会读到2/3的样板文件。另一部分比较棘手:你可以使用宏或者反射。我对宏一无所知,但是有了反射,减少的意义就不会让你想要使用它了:
def generateCodecJson[A](implicit ClassTag[A]): CodecJson[A] = …
而且您仍然需要提供伴生对象并调用该函数来生成CodecJson。不太确定这是否值得努力。
发布于 2016-09-27 12:09:54
我不熟悉Scala。但我认为您在Java中遇到的情况与此类似。在Java中,当你输入一个在当前命名空间中未知的标记时,所有这些代码都是由IDE导入的。您可以尝试使用更好的IDE,例如Intellij IDEA。
https://stackoverflow.com/questions/39724108
复制