json4s反序列化对象与原始对象不匹配

时间:2017-08-07 21:52:46

标签: scala json4s

在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。如果case类只有一个Enumeration,它可以正常工作。这是为什么?我可以通过使用字符串反序列化为case类,然后按照我希望的方式映射到case类来纠正这个问题。有没有办法哄骗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))

编辑:

似乎没有正确反序列化的东西,因为这也构建了匹配的重构对象:

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

但不是这样:

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

1 个答案:

答案 0 :(得分:0)

我把它作为一个解决方案,用于需要在多个Enumerations存在的情况下支持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在没有正确反序列化字段的情况下工作。