2012-06-28 56 views
4

如何使用lift-json反向串行化json數組到scala矢量?使用lift-json進行矢量反序列化

例如:

case class Foo(bar: Vector[Bar]) 

trait Bar { 
    def value: Int 
} 

case class Bar1(value: Int) extends Bar 

case class Bar2(value: Int) extends Bar  

import net.liftweb.json.{ShortTypeHints, Serialization, DefaultFormats} 

implicit val formats = new DefaultFormats { 
    override val typeHintFieldName = "type" 
    override val typeHints = ShortTypeHints(List(classOf[Foo],classOf[Bar1],classOf[Bar2])) 
} 

println(Serialization.writePretty(Foo(Vector(Bar1(1), Bar2(5), Bar1(1))))) 

結果是:

{ 
    "type":"Foo", 
    "bar":[{ 
    "type":"Bar1", 
    "value":1 
    },{ 
    "type":"Bar2", 
    "value":5 
    },{ 
    "type":"Bar1", 
    "value":1 
    }] 
} 

好。但是當我嘗試反序列化此字符串

println(Serialization.read[Foo](Serialization.writePretty(Foo(Vector(Bar1(1), Bar2(5), Bar1(1)))))) 

我得到一個異常:

net.liftweb.json.MappingException:解析的JSON值不匹配 與類的構造函數ARGS =名單(BAR1( 1),BAR2(5),BAR1(1))精氨酸 類型= scala.collection.immutable。$結腸結腸$ =構造公共 test.Foo(scala.collection.immutable.Vector)

這是意味着json arr ay與scala列表關聯,而不是類Foo中定義的向量類型。我知道有辦法通過擴展net.liftweb.json.Serializer來創建自定義序列化器,並將其包含到格式值中。但我怎麼能恢復存儲在矢量中的對象的類型。我想獲得反序列化這樣的結果:

美孚(向量(BAR1(1),BAR2(5),BAR1(1)))

回答

3

我經常被Lift的中心性所困擾,並且發現自己需要在過去做類似的事情。以下是我用過的辦法,適應了一下你的例子:

trait Bar { def value: Int } 
case class Bar1(value: Int) extends Bar 
case class Bar2(value: Int) extends Bar 
case class Foo(bar: Vector[Bar]) 

import net.liftweb.json._ 

implicit val formats = new DefaultFormats { outer => 
    override val typeHintFieldName = "type" 
    override val typeHints = 
    ShortTypeHints(classOf[Bar1] :: classOf[Bar2] :: Nil) + 
    new ShortTypeHints(classOf[Foo] :: Nil) { 
     val FooName = this.hintFor(classOf[Foo]) 
     override def deserialize = { 
     case (FooName, foo) => foo \ "bar" match { 
      case JArray(bars) => Foo(
      bars.map(_.extract[Bar](outer, manifest[Bar]))(collection.breakOut) 
     ) 
      case _ => throw new RuntimeException("Not really a Foo.") 
     } 
     } 
    } 
} 

的醜樣,並很可能被清理了一點,但它的工作原理。

+0

謝謝。對我的例子工作正常。但是,如果有其他類型的矢量有很多,對於所有這些類型,我應該重寫反序列化方法嗎?那麼這個例子呢: '案例分類Bar3(value:Int,bars2:Vector [Bars2])擴展Bar' 還有其他更通用的解決方案嗎? –

1

您可以添加的隱式轉換:

implicit def listToVect(list:List[Bar]):Vector[Bar] = list.map(identity)(breakOut) 

之後,Serialization.read[Foo]按預期工作。

+0

不工作。我認爲這種隱式轉換必須深入方法讀取執行,而不是在這一層。或者你的意思是插入這段代碼? –

+0

我在REPL上試過了。暗示應該在工作範圍內。例如必須在課堂上輸入你需要的東西。 –

相關問題