高效序列化案例类
对于我正在开发的库,我需要提供一种高效、方便且类型安全的序列化 scala 类的方法。理想的情况是用户可以创建一个案例类,并且只要所有成员都是可序列化的,它似乎也应该如此。我准确地知道序列化和反序列化阶段的类型,因此不需要(也不能)将任何“模式”信息作为序列化格式的一部分(如 Java 对象序列化)。
我一直在考虑一些想法,而这个似乎非常接近。我在这里看到的主要问题是用户如何指定类的“应用”和“取消应用”功能。由于这些实际上是静态函数,我想知道是否可以让编译器找到它。
这是一个独立的示例:
trait InOut[T] {
// just keeping things simple, for illustration purposes
def toWire(x: T): Array[Byte]
def fromWire(v: Array[Byte] ): T
}
object InOutConversions {
// Pretend these are implemented properly
implicit def Int = new InOut[Int] {
def toWire(x: Int): Array[Byte] = Array[Byte]()
def fromWire(v: Array[Byte] ): Int = 44
}
implicit def String = new InOut[String] {
def toWire(x: String): Array[Byte] = Array[Byte]()
def fromWire(v: Array[Byte] ): String = "blah"
}
// etc... for all the basic types
}
然后我需要一个像这样的函数:
def serialize2[T, A1 : InOut, A2 : InOut](unapply : T => Option[Product2[A1, A2]])(obj : T) : Array[Byte] = {
val product : Product2[A1, A2] = unapply(obj).get
implicitly[InOut[A1]].toWire(product._1) ++ implicitly[InOut[A2]].toWire(product._2)
}
这将允许用户非常容易地使用它。 但正如
case class Jesus(a: Int, b: String)
val j = Jesus(4, "Testing")
serialize2 (Jesus.unapply(_)) (j)
你所看到的,最后一行真的很恶心。当然一定有可能对此进行改进吗? (鉴于耶稣,我当然可以找到“取消应用”静态方法)
For a library I'm working on, I need to provide an efficient, convenient and typesafe method of serializing scala classes. The ideal would be if a user can create a case class, and as long as all the members are serializable it should seemlessly be so too. I know precisely the type during both the serializing and deserializing stage so there's no need (and can not afford to) have any "schema" information as part of the seriazation format (like the Java object serialisation).
I've been playing with a few ideas, and this one seems to come pretty close. The major problem I see here, is how the user has to specify class's "apply" and "unapply" function. Since these are really static functions, I'm wondering if it's possible to get the compiler to find it.
Here's a self contained example:
trait InOut[T] {
// just keeping things simple, for illustration purposes
def toWire(x: T): Array[Byte]
def fromWire(v: Array[Byte] ): T
}
object InOutConversions {
// Pretend these are implemented properly
implicit def Int = new InOut[Int] {
def toWire(x: Int): Array[Byte] = Array[Byte]()
def fromWire(v: Array[Byte] ): Int = 44
}
implicit def String = new InOut[String] {
def toWire(x: String): Array[Byte] = Array[Byte]()
def fromWire(v: Array[Byte] ): String = "blah"
}
// etc... for all the basic types
}
And then I need a function like this:
def serialize2[T, A1 : InOut, A2 : InOut](unapply : T => Option[Product2[A1, A2]])(obj : T) : Array[Byte] = {
val product : Product2[A1, A2] = unapply(obj).get
implicitly[InOut[A1]].toWire(product._1) ++ implicitly[InOut[A2]].toWire(product._2)
}
Which would allow a user to use it pretty easy. e.g.
case class Jesus(a: Int, b: String)
val j = Jesus(4, "Testing")
serialize2 (Jesus.unapply(_)) (j)
But as you can see, that last line was really quite yuck. Surely it must be possible to improve on that? (Given a Jesus, surely I can find the 'unapply' static method)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于没有获取给定案例类的伴生对象的通用方法,因此您将添加一些额外的工作。我看到三个选项:
unapply
方法。toTuple
方法添加到案例类实例中。例如:
选项 2 的代码示例:
您应该查看SBinary,看起来很相似。
Because don't have a generic way of getting the companion object of a given case class, you will add to do some extra work. I see three options:
unapply
method.toTuple
method to the case class instances.For instance:
Code example for option 2:
You should have a look at SBinary, it looks similar.