加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala Pickling:为嵌套结构编写自定义pickler / unpickler

发布时间:2020-12-16 18:16:14 所属栏目:安全 来源:网络整理
导读:我正在尝试编写一个自定义SPickler / Unpickler对来解决当前 scala-pickling的局限性. 我试图挑选的数据类型是一个案例类,其中一些字段已经拥有自己的SPickler和Unpickler实例. 我想在我的自定义pickler中使用这些实例,但我不知道如何. 这是我的意思的一个例
我正在尝试编写一个自定义SPickler / Unpickler对来解决当前 scala-pickling的局限性.
我试图挑选的数据类型是一个案例类,其中一些字段已经拥有自己的SPickler和Unpickler实例.
我想在我的自定义pickler中使用这些实例,但我不知道如何.

这是我的意思的一个例子:

// Here's a class for which I want a custom SPickler / Unpickler.
// One of its fields can already be pickled,so I'd like to reuse that logic.
case class MyClass[A: SPickler: Unpickler: FastTypeTag](myString: String,a: A)

// Here's my custom pickler.
class MyClassPickler[A: SPickler: Unpickler: FastTypeTag](
  implicit val format: PickleFormat) extends SPickler[MyClass[A]] with Unpickler[MyClass[A]] {
  override def pickle(
    picklee: MyClass[A],builder: PBuilder) {
    builder.beginEntry(picklee)

    // Here we save `myString` in some custom way.
    builder.putField(
      "mySpecialPickler",b => b.hintTag(FastTypeTag.ScalaString).beginEntry(
        picklee.myString).endEntry())

    // Now we need to save `a`,which has an implicit SPickler.
    // But how do we use it?

    builder.endEntry()
  }

  override def unpickle(
    tag: => FastTypeTag[_],reader: PReader): MyClass[A] = {
    reader.beginEntry()

    // First we read the string.
    val myString = reader.readField("mySpecialPickler").unpickle[String]

    // Now we need to read `a`,which has an implicit Unpickler.
    // But how do we use it?
    val a: A = ???

    reader.endEntry()

    MyClass(myString,a)
  }
}

我真的很感激一个有效的例子.
谢谢!

解决方法

这是一个工作示例:

case class MyClass[A](myString: String,a: A)

请注意,MyClass的type参数不需要上下文边界.只有自定义pickler类需要相应的含义:

class MyClassPickler[A](implicit val format: PickleFormat,aTypeTag: FastTypeTag[A],aPickler: SPickler[A],aUnpickler: Unpickler[A])
  extends SPickler[MyClass[A]] with Unpickler[MyClass[A]] {

  private val stringUnpickler = implicitly[Unpickler[String]]

  override def pickle(picklee: MyClass[A],builder: PBuilder) = {
    builder.beginEntry(picklee)

    builder.putField("myString",b => b.hintTag(FastTypeTag.ScalaString).beginEntry(picklee.myString).endEntry()
    )

    builder.putField("a",b => {      
        b.hintTag(aTypeTag)
        aPickler.pickle(picklee.a,b)
      }
    )

    builder.endEntry()
  }

  override def unpickle(tag: => FastTypeTag[_],reader: PReader): MyClass[A] = {
    reader.hintTag(FastTypeTag.ScalaString)
    val tag = reader.beginEntry()
    val myStringUnpickled = stringUnpickler.unpickle(tag,reader).asInstanceOf[String]
    reader.endEntry()

    reader.hintTag(aTypeTag)
    val aTag = reader.beginEntry()
    val aUnpickled = aUnpickler.unpickle(aTag,reader).asInstanceOf[A]
    reader.endEntry()

    MyClass(myStringUnpickled,aUnpickled)
  }

}

除了自定义pickler类之外,我们还需要一个隐式def,它返回一个专门用于具体类型参数的pickler实例:

implicit def myClassPickler[A: SPickler: Unpickler: FastTypeTag](implicit pf: PickleFormat) =
  new MyClassPickler

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读