在 Akka Http 或 http4s 等库中编组的设计模式的名称是什么?

问题描述

在像 akka-http 或 http4s 这样的库中,总是有一种模式,您可以定义对象从/到 JSON 进行编组。当您稍后需要使用序列化时,您可以导入隐式,以便在函数方法中使用它们。

对于一个与 REST apis 无关的项目,我想实现相同的设计模式来将案例类序列化为 RDF。

设计模式的名称是什么?我在哪里可以找到模式的简明描述,这样我就不必对这些库进行逆向工程?

解决方法

使用类型类(用于序列化逻辑)和隐式类(用于扩展方法语法)完成。

创建类型类 - 这是一个通用特征:

trait XmlSerializer[T] { //type class
  type Xml = String
  def asXml(element: T,name: String): Xml
}

创建伴随对象:

object XmlSerializer {
  //easy access to instance by XmlSerializer[User]
  def apply[T](implicit serializer: XmlSerializer[T]): XmlSerializer[T] = serializer

  //implicit class for myUser.asXml("myName") syntax
  //serializer will be injected in compile time
  implicit class RichXmlSerializer[T](val element: T) extends AnyVal {
    def asXml(name: String)(implicit serializer: XmlSerializer[T]) = serializer.asXml(element,name)
  }

  //type class instance
  implicit val stringXmlSerializer: XmlSerializer[String] = new XmlSerializer[String] {
    override def asXml(element: String,name: String) = s"<$name>$element</$name>"
  }
}

为您的模型创建类型类实例:

case class User(id: Int,name: String)

object User {
  implicit val xmlSerializer: XmlSerializer[User] = new XmlSerializer[User] {
    override def asXml(element: User,name: String) = s"<$name><id>${element.id}</id><name>${element.name}</name></$name>"
  }
}

case class Comment(user: User,content: String)

object Comment {
  implicit val xmlSerializer: XmlSerializer[Comment] = new XmlSerializer[Comment] {
    import example.XmlSerializer._ //import fot implicit class syntax

    override def asXml(element: Comment,name: String) = {
      //user serializer is taken from User companion object
      val userXml = element.user.asXml("user")
      val contentXml = element.content.asXml("content")
      s"<$name>$userXml$contentXml</$name>"
    }
  }
}

使用它: object MyApp 扩展 App {

  import example.XmlSerializer._ //import fot implicit class syntax

  val user = User(1,"John")
  val comment = Comment(user,"Hello!")
  println(XmlSerializer[User].asXml(user,"user"))
  println(comment.asXml("comment"))
}

输出:

<user><id>1</id><name>John</name></user>
<comment><user><id>1</id><name>John</name></user><content>Hello!</content></comment>

逻辑执行得不好,但这不是重点。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...