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

Scala json4s反序列化对象与原始对象不匹配,scala,json4s,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")

在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)
这发生在枚举中,但不是其他类型,例如字符串。如果case类只有一个枚举,那么它可以正常工作。为什么呢?我可以通过反序列化到带有字符串的case类,然后映射到我想要的case类来纠正这个问题。有没有办法诱使json4s直接反序列化,使反序列化的对象与原始对象匹配

编辑:

下面是我提到的用于进行映射的hack:

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

编辑:

实际上,不需要单独的序列化程序类:

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))

我把它作为一种解决方案,提供给那些需要在存在多个枚举的情况下支持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)
    }
}

关键在于我们正在构建重构的代码。我们制作一个副本,在此过程中,将thing1转换为字符串并返回枚举。幸运的是,toString可以在字段未被正确反序列化的情况下工作。

我不确定这种情况下的问题是什么,但在过去,为了找出两个对象不匹配的原因,我通常将单个
应该是
语句分解为一系列on语句,对象上的每个字段对应一个,要查看哪个字段不匹配。@Tyler-在这个例子中,有两个枚举,我不确定。但是,如果ThingHolder只有一个Thing1,那么如果第二个EnumNameSerializer留在隐式语句中,它仍然会失败。在这种情况下,只有一个字段会失败。不过,这似乎并没有指向一个解决方案。@Tyler-这就是问题1。请参见第三次编辑。
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)
    }
}