2014-04-14 9 views
9

Ben "dekapaj" seri hale Scala olduğunu kullanmaya çalışıyorum ve ben aynı örneği bunu gösteren bkz:Scala dekapajı: nasıl?

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

Bu örnek, bazı yükseltir:

import scala.pickling._ 
import json._ 

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

Unpickling asitleme kadar kolaydır soru. Her şeyden önce, nesnenin dizgeye dönüştürülmesini atlar. Görünüşe göre json dize temsili almak için pckl.value'u araman gerekiyor.

Çıkarma daha da kafa karıştırıcı. Deserialization, bir nesneye dize (veya bayt) döndürme eylemidir. Bu "örnek", nesnenin dize/binary gösterimi olmadığında nasıl seri hale getirmeyi gösterir?

Peki, basit nesneyi asitleme kitaplığı ile nasıl deserialize edebilirim?

+0

dışarı kontrol ettiniz [testler] (https://github.com/scala/pickling/tree/2.10.x/core/src/test/scala/pickling): İşte bir örnek? Görünüşe göre daha fazla örnek var burada [https://speakerdeck.com/heathermiller/on-pickles-and-spores-improving-support-for-distributed-programming-in-scala). – n0741337

+0

Evet, bu sınamaları kontrol ettim, ancak tam olarak aynı davranışı sergiliyorlar: dize veya bayt dizisini çıkarmazlar, ancak bir turşu kaldırırlar. Elimdeki tek şey json dize ve nesne tipi olduğunda, gerçek dünyadaki turşu nereden geliyor? –

cevap

6

ile değiştirilebilir. Hedeflerinizi gerçekleştirmek için tip sistemini ve vaka sınıflarını kullanın. Hiyerarşinizdeki bazı üstün tiplere (AnyRef dahil) kadar kaldırabilirsiniz.

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) 
    } 
} 
+0

Teşekkürler David, sorduğumuzu (object-> string-> object) artı sormadığım şeyi gösteren iyi bir örnek. (Tip bilinmiyorsa nasıl ele alınır) –

+1

Teşekkürler! Şimdi yaklaşık 30 farklı sınıf ile dekapaj kullanıyorum. Kryo ve Jackson'a kıyasla gerçekten sıfır boilerk. Daha fazla iyilik için Unpickle'ı bir Try() içine sarın. –

0

Bir vaka sınıfının önünü açmak için bir turşu ile başlayacakmış gibi görünüyorsunuz. Ancak JSON dizgisi, başlangıç ​​turülü almak için JSONPickle sınıfına beslenebilir. Burada

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}") 
} 

göre bir örnek baskılı çıktısı:

C([1,2,3]), arr.sum = 6 

I girişi .stripMargin.trim yanı sıra testi içinde "TPE" drop başardı Testten JSON. Hepsi bir satırda çalışıyor, ama daha açık olabileceğini düşündüm. Testten gelen "tpe" nin gelen JSON için tip güvenlik önlemi alması gerekiyorsa bana açık değil.

Kendinizi yuvarlamak istemedikçe, dekapaj için destekledikleri diğer tek sınıf bir BinaryPickle gibi görünüyor. Bu cevapta kodu derlemek için en son scala-pickling snapshot jar requires quasiquotes.


Ben someting daha karmaşık bu sabah çalıştı ve "tpe" Gelen JSON olmayan primatives için gerekli olduğunu keşfetti - (I karışık hangi tefrika dize gerçekten Pickler uyumlu olması gerektiğini işaret) yukarıdaki koda: naturually, bir istisna atma dan unpickling önlemek için jJson giriş değerini nasıl oluşturulacağını anlamaya bir J(None, Some("donut"), Some(47)) üzerine .value kullanmak zorunda

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") 
... 

.

J için çıkış gibidir:

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

this test bakıldığında görünen gelen JSON tüm primatives veya vaka sınıfları (veya kombinasyonları) JSONPickle sihirli eserler olduğunu, ancak bazı diğer sınıflar gibi ise Seçeneklerin doğru şekilde kaldırılması için ekstra "tpe" tipi bilgiler gereklidir.

+0

Sorunum satır # 23: https://github.com/scala/pickling/blob/2.10.x/core/src/test/scala/pickling/array-json.scala#L23 Bu, dizi [1..3], ve daha sonra dizi [1..3] ile JSON unpickle gerçekleştirir. Bu yüzden anlamıyorum, ne test ediliyor. Bu testin sonucunun JSON'dan gelip turşu açık kurucusundan gelmediğini nasıl bilebilirim? Bu test, serileştirmenin sonucunun ne olduğunu bildiğimizi varsayar, fakat nokta ne kadardır? –

+0

Tüm sürecin, turşu her iki ucu hakkında bilgi gerektirdiği konusunda haklısınız. Onların çalışma noktası yansımalarını önlemek için seçimler yaptıkları ve derleme zaman kodu genişlemesini kullanmayı tercih ettikleri noktaların hızlı, dizisel serializatin/deserialization olduğunu düşünüyorum. İlk örneğimde olduğu gibi bir JSON dizesinden ilkel öğelerle bir sınıf sınıfı yüklemek, JSONPickle sınıfı tarafından izin verilen özel bir durum gibi görünüyor. Bununla birlikte, Seçeneklerin işlenmesinde ve eksik JSON üyeleri için varsayılan değerleri uygularken görünmüyorsa, ayrıştırma sırasında yardıma ihtiyaç duyduğu anlamda genel bir JSON ayrıştırıcısı değildir. – n0741337

2

Tamam, sanırım anladım.

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

Yani, biz her türlü turşu aynı şekilde, dize unpickle edebilirsiniz:

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 dizesi üretecek. Serileştirme tipi, "json. " belgesinde bildirilen örtülü biçimlendirici tarafından düzenlenir ve "binary."