所以我一直在嘗試在Scala中編寫JSON解析器。到目前爲止,我已經嘗試過Jackson,gson和flexjson,但是我無法使用它包含我的示例。 這個例子看起來很愚蠢,但它證明了我的問題。Json序列化,Scala中的反序列化與集合和循環依賴
我得到的最長時間是與傑克遜一起使用註釋。
@JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class)
我想要保存的每個類。這似乎創建了一個正確的JSON文件,但我無法將其反序列化回我的Garage對象。 這種方法的一個問題也是註釋,如果可能的話我想跳過註釋,因爲在我的實例中我沒有完全控制源代碼。
我已經在下面插入了所有的代碼(傑克遜例子)和我的依賴(以gradle格式)。
代碼:
import java.io.StringWriter
import com.fasterxml.jackson.annotation.{JsonIdentityInfo, ObjectIdGenerators}
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
object JsonTester extends App {
trait TestData {
var volvo1 = new Car(null, "volvo")
var volvo2 = new Car(null, "volvo")
var bmw = new Car(null, "bmw")
var jeep1 = new Car(null, "jeep")
var jeep2 = new Car(null, "jeep")
var ford = new Car(null, "ford")
val p1 = new Person("John", List[Car](volvo1, jeep1))
volvo1.owner = p1
jeep1.owner = p1
val p2 = new Person("Anna", List[Car](volvo2))
volvo2.owner = p2
val p3 = new Person("Maria", List[Car](bmw))
bmw.owner = p3
val p4 = new Person("Kevin", List(ford, jeep2))
ford.owner = p4
jeep2.owner = p4
val customers = List(p1, p2, p3, p4)
val carModels = Map("volvo" -> List(volvo1, volvo2), "bmw" -> List(bmw), "jeep" -> List(jeep1, jeep2), "ford" -> List(ford))
val garage = new Garage[Person, Car]("FixYourCar", customers, carModels);
}
new TestData() {
val originalToString = garage.toString
println("Garage: " + originalToString)
val json: String = toJson(garage)
println(json)
val garageFromJson: Garage[Person, Car] = fromJson(json)
println("garageFromJson: " + garageFromJson)
garageFromJson.customers.foreach(println(_))
assert(originalToString.equals(garageFromJson.toString))
}
def toJson(garage: Garage[Person, Car]): String = {
import com.fasterxml.jackson.module.scala.DefaultScalaModule
val mapper = new ObjectMapper()
mapper.registerModule(DefaultScalaModule)
println("Saving graph to json")
val writer = new StringWriter()
mapper.writeValue(writer, garage)
writer.toString
}
def fromJson(json: String): Garage[Person, Car] = {
val mapper = new ObjectMapper()
mapper.registerModule(DefaultScalaModule)
mapper.readValue[Garage[Person, Car]](json, classOf[Garage[Person, Car]])
}
}
@JsonIdentityInfo(generator = classOf[ObjectIdGenerators.UUIDGenerator])
case class Garage[P, C](name: String, customers: List[P], models: Map[String, List[C]])
@JsonIdentityInfo(generator = classOf[ObjectIdGenerators.UUIDGenerator])
case class Person(name: String, cars: List[Car])
@JsonIdentityInfo(generator = classOf[ObjectIdGenerators.UUIDGenerator])
case class Car(var owner: Person, model: String) {
override def toString(): String = s"model: $model, owner:${owner.name}"
}
依賴關係: 編譯 'org.scala浪:斯卡拉庫:2.11.2' 編譯 「org.scalatest:scalatest_2.11:2.2.2」
從運行compile 'com.typesafe.akka:akka-actor_2.11:2.3.6'
compile 'com.typesafe.akka:akka-testkit_2.11:2.3.6'
compile 'net.sf.opencsv:opencsv:2.3'
compile 'jfree:jcommon:1.0.16'
compile 'org.jfree:jfreechart:1.0.15'
compile 'org.jgrapht:jgrapht-ext:0.9.0'
compile 'org.hibernate:hibernate-core:3.6.0.Final'
compile 'org.hibernate:hibernate-entitymanager:3.6.0.Final'
compile 'mysql:mysql-connector-java:5.1.27'
// json
compile 'com.fasterxml.jackson.module:jackson-module-scala_2.11:2.4.2'
compile 'com.google.code.gson:gson:2.3'
compile 'net.sf.flexjson:flexjson:3.2'
結果:
Garage: .....
Saving graph to json
{"@id":"282559ae-70ea-4d74-8363-4b37f1691dba"....
garageFromJson: Garage(FixYourCar,List(Map(@id -> 7ae4b765-c0dc-4a8e-867f-23bc7672db91, name -> John, cars -> ....
Exception in thread "main" java.lang.ExceptionInInitializerError
at JsonTester.main(JsonTester.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: java.lang.ClassCastException: scala.collection.immutable.Map$Map3 cannot be cast to Person
at JsonTester$$anon$1$$anonfun$1.apply(JsonTester.scala:49)
at scala.collection.immutable.List.foreach(List.scala:381)
at JsonTester$$anon$1.<init>(JsonTester.scala:49)
at JsonTester$.<init>(JsonTester.scala:40)
at JsonTester$.<clinit>(JsonTester.scala)
... 6 more
你是什麼意思的循環依賴?另外:'Car'的第一個參數是什麼(放置'null'值的地方)?關於註釋:你知道json4s嗎?它建立在jackson上,並提供了一個整潔的,自動的序列化/反序列化的case類。 https://github.com/json4s/json4s – 2014-09-27 01:43:48
沒關係,我想通了你的意思是循環依賴。你的'Car'有一個'Person',但是'Person'也有'Car'。那麼......我認爲這不適用於大小寫常量的case類,因爲你永遠無法同時初始化它們。也許你可以將你的JSON反序列化爲輔助對象,然後將它們轉換成你想要的'Car's和'Person's? – 2014-09-27 02:03:05