在 Akka Http 或 http4s 等库中编组的设计模式的名称是什么?
What is the name of the design pattern for marshalling in libraries like Akka Http or http4s?
在像 akka-http 或 http4s 这样的库中,总是有一种模式,您可以在其中定义执行编组的对象 from/to JSON。当您以后需要使用序列化时,您可以导入隐含函数,以便在函数方法中使用它们。
对于一个与 REST api 无关的项目,我想实现相同的设计模式以将 case 类 序列化为 RDF。
设计模式的名称是什么?我在哪里可以找到该模式的简明描述,这样我就不必对这些库进行逆向工程?
它是使用类型 class(用于序列化逻辑)和隐式 class(用于扩展方法语法)完成的。
创建类型 class - 这是一个通用特征:
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>"
}
}
为您的模型创建类型 classes 实例:
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>"
}
}
}
使用它:
对象 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>
逻辑执行得不好,但这不是重点
在像 akka-http 或 http4s 这样的库中,总是有一种模式,您可以在其中定义执行编组的对象 from/to JSON。当您以后需要使用序列化时,您可以导入隐含函数,以便在函数方法中使用它们。
对于一个与 REST api 无关的项目,我想实现相同的设计模式以将 case 类 序列化为 RDF。
设计模式的名称是什么?我在哪里可以找到该模式的简明描述,这样我就不必对这些库进行逆向工程?
它是使用类型 class(用于序列化逻辑)和隐式 class(用于扩展方法语法)完成的。
创建类型 class - 这是一个通用特征:
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>"
}
}
为您的模型创建类型 classes 实例:
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>"
}
}
}
使用它: 对象 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>
逻辑执行得不好,但这不是重点