9

我正在尝试使用“酸洗”序列化是 Scala,我看到相同的示例演示它:

import scala.pickling._
import json._

val pckl = List(1, 2, 3, 4).pickle

解酸就像酸洗一样简单:

val lst = pckl.unpickle[List[Int]]

这个例子提出了一些问题。首先,它跳过了对象到字符串的转换。显然你需要调用 pckl.value 来获取 json 字符串表示。

Unpickling 更加令人困惑。反序列化是将字符串(或字节)转换为对象的行为。如果没有对象的字符串/二进制表示,这个“示例”如何演示反序列化?

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

4

3 回答 3

6

使用类型系统和案例类来实现您的目标。您可以取消选择层次结构中的某些高级类型(直到并包括 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)
  }
}
于 2014-06-01T14:39:17.970 回答
3

Ok, I think I understood it.

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

will produce JSON string:

{
  "tpe": "scala.Array[scala.Int]",
  "value": [
    1,
    2,
    3
  ]
}

So, the same way we pickle any type, we can unpickle string. Type of serialization is regulated by implicit formatter declared in "json." and can be replaced by "binary."

于 2014-04-15T18:13:47.107 回答
0

看起来你将从一个泡菜开始解封到一个案例类。但是可以将 JSON 字符串提供给 JSONPickle 类以获取起始泡菜。

这是一个基于他们的 array-json 测试的示例

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”以及从测试中删除.stripMargin.trim输入 JSON。它在一行中起作用,但我认为它可能会更明显地分开。我不清楚测试中的“tpe”是否应该为传入的 JSON 提供类型安全的度量。

看起来他们支持酸洗的唯一其他类是 BinaryPickle 除非你想自己动手。最新的 scala-pickling 快照 jar需要 quasiquotes来编译此答案中的代码。


今天早上我尝试了一些更复杂的东西,发现传入的 JSON 中的非原始数据需要“tpe” - 这指出序列化的字符串确实必须与 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" )
...

自然地,我不得不使用.valueaJ(None, Some("donut"), Some(47))来确定如何创建jJson输入值以防止 unpickling 引发异常。

的输出J如下:

J(None, Some(donut), Some(47)) 

看看这个测试,如果传入的 JSON 是 JSONPickle 魔法起作用的所有基元或案例类(或组合),但像 Options 这样的其他一些类需要额外的“tpe”类型信息才能正确解压。

于 2014-04-15T07:21:49.843 回答