2017-08-07 61 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没有正确反序列化字段。