2017-08-07 65 views
2

在Scala中2.10.6,使用json4s 3.2.11,向其中我現在約束爲,使用以下代碼:json4s反序列化對象不匹配原始

object Thing1 extends Enumeration { 
    type Thing1 = Value 
    val A = Value(0, "A") 
    val B = Value(1, "B") 
} 

object Thing2 extends Enumeration { 
    type Thing2 = Value 
    val A = Value(0, "A") 
    val B = Value(1, "B") 
    val C = Value(2, "C") 
} 

case class ThingHolder(thing1: Thing1, thing2: Thing2) 

class ThingSpec extends FlatSpec with Matchers { 
    "desrialized" should "match original" in { 
     import org.json4s.native.Serialization.writePretty 
     implicit val formats = DefaultFormats + new EnumNameSerializer(Thing1) + new EnumNameSerializer(Thing2) 

     val original = ThingHolder(Thing1.A, Thing2.C) 
     println(original) 

     val serialized = writePretty(original) 
     println(serialized) 

     val jValue = JsonParser.parse(serialized) 
     val deserialized = jValue.camelizeKeys.extract[ThingHolder] 
     println(deserialized) 
     println(deserialized.thing1) 

     deserialized should be(original) 
    } 
} 

結果:

ThingHolder(A,C) 
{ 
    "thing1":"A", 
    "thing2":"C" 
} 
ThingHolder(A,C) 
A 

ThingHolder(A,C) was not equal to ThingHolder(A,C) 

這發生在枚舉上,但不是另一種類型,例如String。如果case類只有一個Enumeration,它就可以正常工作。這是爲什麼?我可以通過反序列化到帶有字符串的案例類,然後根據需要映射到案例類來更正此問題。有沒有辦法讓json4s直接反序列化,以便反序列化的對象與原始對象匹配?

編輯:

這是我提到做映射破解:

case class ThingHolderSerialized(thing1: String, thing2: String) 

...

val deserialized = jValue.camelizeKeys.extract[ThingHolderSerialized] 
val reconstituted = ThingHolder(Thing1.withName(deserialized.thing1), Thing2.withName(deserialized.thing2)) 

編輯:

實際上,單獨序列化器類是不必要的:

val deserialized = jValue.camelizeKeys.extract[ThingHolder] 
val reconstituted = ThingHolder(Thing1.withName(deserialized.thing1.toString), Thing2.withName(deserialized.thing2.toString)) 

編輯:

看來,這是thing1這不是正確的反序列化,因爲這也是建立一個匹配的重組對象:

val reconstituted = deserialized.copy(thing1 = Thing1.withName(deserialized.thing1.toString)) 

但不是這樣的:

val reconstituted = deserialized.copy(thing2 = Thing2.withName(deserialized.thing2.toString)) 
+0

我不確定在這種情況下出現了什麼問題,但是在過去弄清楚爲什麼兩個對象不匹配我通常會將我單個的「應該」語句分解爲一系列語句,每個字段對應一個該對象,確切地看到哪個字段不匹配。 – Tyler

+0

@泰勒 - 在這個例子中,有兩個枚舉,我不確定。但是,如果ThingHolder只有Thing1,如果第二個EnumNameSerializer留在隱式語句中,它仍然會失敗。在這種情況下,只有一個領域失敗。但這似乎並不指向解決方案。 –

+0

@泰勒 - 這是事1。見第三個編輯。 –

回答

0

我m把它作爲一個解決方案,用於需要在多個枚舉存在的情況下支持json4s案例類反序列化的人員。這不是我要找的答案,但在此期間的工作原理:

object Thing1 extends Enumeration { 
    type Thing1 = Value 
    val A = Value(0, "A") 
    val B = Value(1, "B") 
} 

object Thing2 extends Enumeration { 
    type Thing2 = Value 
    val A = Value(0, "A") 
    val B = Value(1, "B") 
    val C = Value(2, "C") 
} 

case class ThingHolder(thing1: Thing1, thing2: Thing2) 

class ThingSpec extends FlatSpec with Matchers { 
    "reconstituted" should "match original" in { 
     import org.json4s.native.Serialization.writePretty 
     implicit val formats = DefaultFormats + new EnumNameSerializer(Thing1) + new EnumNameSerializer(Thing2) 

     val original = ThingHolder(Thing1.A, Thing2.C) 
     println(original) 

     val serialized = writePretty(original) 
     println(serialized) 

     val jValue = JsonParser.parse(serialized) 
     val deserialized = jValue.camelizeKeys.extract[ThingHolder] 
     println(deserialized) 

     val reconstituted = deserialized.copy(thing1 = Thing1.withName(deserialized.thing1.toString)) 
     reconstituted should be(original) 
    } 
} 

的關鍵是在我們正在建設reconstituted行。我們製作一個副本,並在此過程中,將thing1轉換爲字符串並返回枚舉。幸運的是,toString沒有正確反序列化字段。