斯卡拉酸洗:怎么样?

时间:2014-04-14 23:26:42

标签: scala serialization scala-pickling

我正在尝试使用“酸洗”序列化是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表示,这个“示例”如何演示反序列化?

那么,如何用酸洗库反序列化简单对象?

3 个答案:

答案 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。

以下是基于their array-json test

的示例
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"输入信息以正确地解开。