Маринование скалы: как?

Я пытаюсь использовать сериализацию "травления" в Scala, и я вижу тот же пример, демонстрирующий это:

import scala.pickling._
import json._

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

Разрыхление так же просто, как травление:

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

Этот пример поднимает некоторый вопрос. Прежде всего, он пропускает преобразование объекта в строку. По-видимому, вам нужно вызвать pckl.value, чтобы получить строковое представление json.

Распахивание еще более сбивает с толку. Десериализация - это процесс превращения строки (или байтов) в объект. Почему этот "пример" демонстрирует десериализацию, если нет строкового / двоичного представления объекта?

Итак, как мне десериализовать простой объект с помощью библиотеки травления?

3 ответа

Решение

Используйте систему типов и тематические классы для достижения ваших целей. Вы можете отменить выбор какого-либо более высокого типа в вашей иерархии (вплоть до 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)
  }
}

Хорошо, я думаю, что понял это.

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", и может быть заменен "двоичным".

Похоже, вы начнете с рассола, чтобы распаковать его в классе дел. Но строка 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, если вы не хотите выкатить свой собственный. В последнем jar-снимке scala-pickling требуются кавычки для компиляции кода в этом ответе.


Этим утром я попытался сделать что-то более сложное и обнаружил, что "tpe" требуется для непримативов во входящем JSON - что указывает на то, что сериализованная строка действительно должна быть совместима со средством выбора (которое я смешал с приведенным выше кодом):

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 входное значение, чтобы исключить выбрасывание исключением.

Выход для J как:

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

Глядя на этот тест, кажется, что если входящий JSON - это все примитивы или классы дел (или комбинации), то магия JSONPickle работает, но некоторым другим классам, таким как Options, требуется дополнительная информация о типе "tpe" для правильной распаковки.

Другие вопросы по тегам