Lift Framework не может десетировать данные JSON
Вопрос
Я пытаюсь исключить текст JSON, используя Framework Frame, и она не отображается, что они поддерживают черта SEQ (хотя список поддерживается). Например...
Некоторые данные JSON, представляющие сотрудников (с первой и фамилией) ...
{"employees":[{"fname":"Bob","lname":"Hope"},{"fname":"Bob","lname":"Smith"}]}
Вот объекты домена сотрудника:
case class Employee(fname: String, lname: String) { }
case class Employees(employees: Seq[Employee]) { }
И вот мой код десериализации JSON ...
class EmployeeTest {
@Test def test() {
val jsonText: String = ....
val e = deserialize(jsonText)
}
def deserialize(in: String): Employees = {
implicit val formats = net.liftweb.json.DefaultFormats
net.liftweb.json.Serialization.read[Employees](in)
}
}
Если я изменим объект домена сотрудников, чтобы использовать список вместо SEQ, то он работает. Но я бы очень хотел использовать SEQ, если смогу.
Вот исключение, которое я вижу, когда я бегу вышеуказанный код (с помощью SEQ): есть ли что-нибудь, что я могу сделать, чтобы сделать это на работу? Спасибо за вашу помощь!
net.liftweb.json.MappingException: unknown error
at net.liftweb.json.Extraction$.extract(Extraction.scala:43)
at net.liftweb.json.JsonAST$JValue.extract(JsonAST.scala:288)
at net.liftweb.json.Serialization$.read(Serialization.scala:50)
at EmployeeTest.deserialize(EmployeeTest.scala:20)
at EmployeeTest.test(EmployeeTest.scala:13)
Caused by: java.lang.UnsupportedOperationException: tail of empty list
at scala.collection.immutable.Nil$.tail(List.scala:388)
at scala.collection.immutable.Nil$.tail(List.scala:383)
at net.liftweb.json.Meta$Constructor.bestMatching(Meta.scala:60)
at net.liftweb.json.Extraction$.findBestConstructor$1(Extraction.scala:187)
at net.liftweb.json.Extraction$.instantiate$1(Extraction.scala:192)
at net.liftweb.json.Extraction$.newInstance$1(Extraction.scala:222)
at net.liftweb.json.Extraction$.build$1(Extraction.scala:240)
at net.liftweb.json.Extraction$.mkValue$1(Extraction.scala:269)
at net.liftweb.json.Extraction$.build$1(Extraction.scala:242)
at net.liftweb.json.Extraction$$anonfun$4.apply(Extraction.scala:194)
at net.liftweb.json.Extraction$$anonfun$4.apply(Extraction.scala:194)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:206)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:206)
at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:61)
at scala.collection.immutable.List.foreach(List.scala:45)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:206)
at scala.collection.immutable.List.map(List.scala:45)
at net.liftweb.json.Extraction$.instantiate$1(Extraction.scala:194)
at net.liftweb.json.Extraction$.newInstance$1(Extraction.scala:222)
at net.liftweb.json.Extraction$.build$1(Extraction.scala:240)
at net.liftweb.json.Extraction$.extract(Extraction.scala:284)
at net.liftweb.json.Extraction$.extract0(Extraction.scala:172)
at net.liftweb.json.Extraction$.extract(Extraction.scala:40)
... 33 more
Решение
SEQ не поддерживается в сериализации, потому что он не является бетонным типом. Во время десериализации нет информации о типах, которая может быть использована для определения конкретной реализации. Мы могли бы использовать, например, список экземпляров как реализацию по умолчанию, но затем следующее свойство больше не будет держать для всех типов:
deserialize(serialize(x)) == x
Этот конкретный случай может быть десериализирован следующим образом:
import net.liftweb.json._
import net.liftweb.json.JsonAST._
case class Employee(fname: String, lname: String)
case class Employees(employees: Seq[Employee])
object Test extends Application {
implicit val formats = DefaultFormats
val s = """ {"employees":[{"fname":"Bob","lname":"Hope"},{"fname":"Bob","lname":"Smith"}]} """
val json = JsonParser.parse(s)
val employees = Employees(for {
JArray(emps) <- json \ "employees"
emp <- emps
} yield emp.extract[Employee])
println(employees)
}