我正在尝试使用“酸洗”序列化是Scala,我看到同样的例子证明了它:
import scala.pickling._
import json._
val pckl = List(1, 2, 3, 4).pickle
Unpickling就像腌制一样简单:
val lst = pckl.unpickle[List[Int]]
这个例子提出了一些问题。首先,它跳过将对象转换为字符串。显然你需要调用pckl.value来获取json字符串表示。
Unpickling更令人困惑。反序列化是将字符串(或字节)转换为对象的行为。如果没有对象的字符串/ binry表示,这个“示例”如何演示反序列化?
那么,如何用酸洗库反序列化简单对象?
答案 0 :(得分:6)
使用类型系统和案例类来实现您的目标。您可以在层次结构中对某些优秀类型进行unpickle(包括AnyRef)。这是一个例子:
trait Zero
case class One(a:Int) extends Zero
case class Two(s:String) extends Zero
object Test extends App {
import scala.pickling._
import json._
// String that can be sent down a wire
val wire: String = Two("abc").pickle.value
// On the other side, just use a case class
wire.unpickle[Zero] match {
case One(a) => println(a)
case Two(s) => println(s)
case unknown => println(unknown.getClass.getCanonicalName)
}
}
答案 1 :(得分:2)
好的,我想我明白了。
import scala.pickling._
import json._
var str = Array(1,2,3).pickle.value // this is JSON string
println(str)
val x = str.unpickle[Array[Int]] // unpickle from string
将生成JSON字符串:
{
"tpe": "scala.Array[scala.Int]",
"value": [
1,
2,
3
]
}
所以,就像我们挑选任何类型一样,我们可以解开字符串。序列化的类型由" json中声明的隐式格式化程序控制。"并且可以用"二进制代替。"
答案 2 :(得分:0)
看起来你会开始用一个泡菜来挑选案例类。但是JSON字符串可以被提供给JSONPickle类以获得起始的pickle。
的示例package so
import scala.pickling._
import json._
case class C(arr: Array[Int]) { override def toString = s"""C(${arr.mkString("[", ",", "]")})""" }
object PickleTester extends App {
val json = """{"arr":[ 1, 2, 3 ]}"""
val cPickle = JSONPickle( json )
val unpickledC: C = cPickle.unpickle[C]
println( s"$unpickledC, arr.sum = ${unpickledC.arr.sum}" )
}
打印的输出是:
C([1,2,3]), arr.sum = 6
我能够放弃" tpe"来自测试以及来自测试的输入JSON的.stripMargin.trim
。它可以在一条线上工作,但我认为它可能更明显分裂。我不清楚这是不是" tpe"从测试中可以为传入的JSON提供类型安全措施。
看起来他们支持酸洗的唯一其他类是BinaryPickle,除非你想自己动手。最新的scala-pickling快照jar requires quasiquotes用于编译此答案中的代码。
今天早上我尝试了更复杂的事情,并发现" tpe"传入JSON中的非主数据库是必需的 - 它指出序列化字符串确实必须与pickler(我混合到上面的代码中)兼容:
case class J(a: Option[Boolean], b: Option[String], c: Option[Int]) { override def toString = s"J($a, $b, $c)" }
...
val jJson = """{"a": {"tpe": "scala.None.type"},
| "b":{"tpe": "scala.Some[java.lang.String]","x":"donut"},
| "c":{"tpe": "scala.Some[scala.Int]","x":47}}"""
val jPickle = JSONPickle( jJson.stripMargin.trim )
val unpickledJ: J = jPickle.unpickle[J]
println( s"$unpickledJ" )
...
天然地,我必须在.value
上使用J(None, Some("donut"), Some(47))
来弄清楚如何创建jJson
输入值以防止unpickling抛出异常。
J
的输出如下:
J(None, Some(donut), Some(47))
看this test,看来如果传入的JSON是JSONPickle魔法所有的原始类或案例类(或组合),但其他一些类如Options需要额外的" tpe"输入信息以正确地解开。