gpt4 book ai didi

Scala 酸洗 : Writing a custom pickler/unpickler for nested structures

转载 作者:行者123 更新时间:2023-12-04 19:08:12 26 4
gpt4 key购买 nike

我正在尝试编写一个自定义的 SPickler/Unpickler 对来解决当前 scala-pickling 的一些限制。
我试图pickle 的数据类型是一个case 类,其中一些字段已经有自己的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的类型参数不需要上下文边界。只有自定义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

关于Scala 酸洗 : Writing a custom pickler/unpickler for nested structures,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19217725/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com