【发布时间】:2017-08-07 21:52:46
【问题描述】:
在 Scala 2.10.6 中,使用我现在受限的 json4s 3.2.11,使用以下代码:
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)
这发生在 Enumeration 中,但不是其他类型,例如 String。如果案例类只有一个枚举,它工作正常。这是为什么?我可以通过反序列化到带有字符串的案例类来纠正这个问题,然后按照我想要的方式映射到案例类。有没有办法哄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))
【问题讨论】:
-
我不确定在这种情况下问题出在哪里,但过去为了弄清楚为什么两个对象不匹配,我通常将我的单个
should be语句分解为一系列语句,一个对于对象上的每个字段,准确查看哪个字段不匹配。 -
@Tyler - 在这个例子中,有两个枚举,我不确定。但是,如果 ThingHolder 只有一个 Thing1,如果将第二个 EnumNameSerializer 留在隐式语句中,它仍然会失败。在这种情况下,只有一个字段会失败。不过,这似乎并不意味着解决方案。
-
@Tyler - 这就是事情1。见第三次编辑。