使用lift-json实现矢量反序列化

使用lift-json实现矢量反序列化,json,scala,lift,lift-json,Json,Scala,Lift,Lift Json,如何使用提升json到scala向量反序列化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, DefaultF

如何使用提升json到scala向量反序列化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)))))
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.")
        }
      }
    }
}
结果是:

{
  "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=List(Bar1(1)、Bar2(5)、Bar1(1))arg types=scala.collection.immutable.$colon$colon构造函数=public test.Foo(scala.collection.immutable.Vector)

这意味着与scala列表关联的json数组,而不是在类Foo中定义的向量类型。我知道有一种方法可以通过扩展net.liftweb.json.serializer并将其包含到格式值中来创建自定义序列化程序。但如何恢复存储在Vector中的对象类型呢。我想得到如下反序列化的结果:

Foo(向量(Bar1(1)、Bar2(5)、Bar1(1)))


您可以添加隐式转换:

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

在那之后,
Serialization.read[Foo]
就像预期的那样工作。

我经常被Lift的
列表
中心性所困扰,我发现自己过去也需要做类似的事情。以下是我使用的方法,根据您的示例稍作调整:

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

有点难看,可能需要清理一下,但它能用。

不行。我认为这种隐式转换必须深入方法读取执行,而不是在这一层。或者你想在哪里插入这个代码?我在REPL上试过了。隐式应在工作范围内。e、 g.必须在课堂上导入。您需要它们。谢谢。我的例子很好用。但若有许多向量具有其他类型,对于所有这些类型,我应该重写反序列化方法吗?那么这个例子呢:
case类Bar3(value:Int,bars2:Vector[bars2])扩展了Bar
还有其他更通用的解决方案吗?