【问题标题】:Kotlin inheritance: Objects are not equal after serialization and deserialization to / from jsonKotlin继承:在序列化和反序列化到/从json之后对象不相等
【发布时间】:2019-06-12 12:59:48
【问题描述】:

我有继承的 kotlin 类:

abstract class Classification(
        val accuracy: Double
)
@Document
class OrderForm(
        @Id
        val id: String,
        accuracy: Double,
        val customerNumber: String,
        val orders: List<Order>
) : Classification(accuracy)

并且我实现了一个序列化测试:

internal class OrderFormTest : Logging {

    private val objectMapper = ObjectMapper().registerKotlinModule()

    @Test
    fun canBeSerialisedToJsonAndBack() {
        val expected = OrderForm(
                "123_ID",
                94.77,
                "123_CUSTOMER",
                listOf(
                        Order(
                                0.0,
                                OrderNumber(
                                        10.0,
                                        123456789L),
                                OrderSize(
                                        99.99,
                                        "38/40"),
                                OrderAmount(
                                        100.0,
                                        7),
                                OrderPrice(
                                        50.0,
                                        999.99),
                                OrderPage(
                                        23.29343,
                                        100)
                        ),
                        Order(
                                0.0,
                                OrderNumber(
                                        10.0,
                                        123456789L),
                                OrderSize(
                                        99.99,
                                        "38/40"),
                                OrderAmount(
                                        100.0,
                                        7),
                                OrderPrice(
                                        50.0,
                                        999.99),
                                OrderPage(
                                        23.29343,
                                        100)
                        )
                )
        )

        logger.info("expected: $expected")

        val json = objectMapper.writeValueAsString(expected)

        logger.info("json: $json")

        val result: OrderForm = objectMapper.readValue(json)

        logger.info("result: $result")

        val json2 = objectMapper.writeValueAsString(result);

        logger.info("json: $json2")

        Assertions.assertThat(result).isEqualTo(expected)
    }
}

日志输出:

14:57:37.031 [main] OrderFormTest - expected: de.fronetic.witt.ml.backend.model.OrderForm@4b34fff9
14:57:37.623 [main] OrderFormTest - json: {"id":"123_ID","accuracy":94.77,"customerNumber":"123_CUSTOMER","orders":[{"accuracy":0.0,"orderNumber":{"accuracy":10.0,"number":123456789},"orderSize":{"accuracy":99.99,"size":"38/40"},"orderAmount":{"accuracy":100.0,"amount":7},"orderPrice":{"accuracy":50.0,"price":999.99},"orderPage":{"accuracy":23.29343,"page":100}},{"accuracy":0.0,"orderNumber":{"accuracy":10.0,"number":123456789},"orderSize":{"accuracy":99.99,"size":"38/40"},"orderAmount":{"accuracy":100.0,"amount":7},"orderPrice":{"accuracy":50.0,"price":999.99},"orderPage":{"accuracy":23.29343,"page":100}}]}
14:57:37.673 [main] OrderFormTest - result: de.fronetic.witt.ml.backend.model.OrderForm@38b972d7
14:57:37.674 [main] OrderFormTest - json: {"id":"123_ID","accuracy":94.77,"customerNumber":"123_CUSTOMER","orders":[{"accuracy":0.0,"orderNumber":{"accuracy":10.0,"number":123456789},"orderSize":{"accuracy":99.99,"size":"38/40"},"orderAmount":{"accuracy":100.0,"amount":7},"orderPrice":{"accuracy":50.0,"price":999.99},"orderPage":{"accuracy":23.29343,"page":100}},{"accuracy":0.0,"orderNumber":{"accuracy":10.0,"number":123456789},"orderSize":{"accuracy":99.99,"size":"38/40"},"orderAmount":{"accuracy":100.0,"amount":7},"orderPrice":{"accuracy":50.0,"price":999.99},"orderPage":{"accuracy":23.29343,"page":100}}]}

所以对象的内容完全一样,但对象本身不相等!

如果我不使用继承,这不会发生:

@Document
data class OrderForm(
        @Id
        val id: String,
        val accuracy: Double,
        val customerNumber: String,
        val orders: List<Order>
)

日志输出:

14:59:03.889 [main] OrderFormTest - expected: OrderForm(id=123_ID, accuracy=94.77, customerNumber=123_CUSTOMER, orders=[Order(accuracy=0.0, orderNumber=OrderNumber(accuracy=10.0, number=123456789), orderSize=OrderSize(accuracy=99.99, size=38/40), orderAmount=OrderAmount(accuracy=100.0, amount=7), orderPrice=OrderPrice(accuracy=50.0, price=999.99), orderPage=OrderPage(accuracy=23.29343, page=100)), Order(accuracy=0.0, orderNumber=OrderNumber(accuracy=10.0, number=123456789), orderSize=OrderSize(accuracy=99.99, size=38/40), orderAmount=OrderAmount(accuracy=100.0, amount=7), orderPrice=OrderPrice(accuracy=50.0, price=999.99), orderPage=OrderPage(accuracy=23.29343, page=100))])
14:59:04.833 [main] OrderFormTest - json: {"id":"123_ID","accuracy":94.77,"customerNumber":"123_CUSTOMER","orders":[{"accuracy":0.0,"orderNumber":{"accuracy":10.0,"number":123456789},"orderSize":{"accuracy":99.99,"size":"38/40"},"orderAmount":{"accuracy":100.0,"amount":7},"orderPrice":{"accuracy":50.0,"price":999.99},"orderPage":{"accuracy":23.29343,"page":100}},{"accuracy":0.0,"orderNumber":{"accuracy":10.0,"number":123456789},"orderSize":{"accuracy":99.99,"size":"38/40"},"orderAmount":{"accuracy":100.0,"amount":7},"orderPrice":{"accuracy":50.0,"price":999.99},"orderPage":{"accuracy":23.29343,"page":100}}]}
14:59:04.913 [main] OrderFormTest - result: OrderForm(id=123_ID, accuracy=94.77, customerNumber=123_CUSTOMER, orders=[Order(accuracy=0.0, orderNumber=OrderNumber(accuracy=10.0, number=123456789), orderSize=OrderSize(accuracy=99.99, size=38/40), orderAmount=OrderAmount(accuracy=100.0, amount=7), orderPrice=OrderPrice(accuracy=50.0, price=999.99), orderPage=OrderPage(accuracy=23.29343, page=100)), Order(accuracy=0.0, orderNumber=OrderNumber(accuracy=10.0, number=123456789), orderSize=OrderSize(accuracy=99.99, size=38/40), orderAmount=OrderAmount(accuracy=100.0, amount=7), orderPrice=OrderPrice(accuracy=50.0, price=999.99), orderPage=OrderPage(accuracy=23.29343, page=100))])
14:59:04.914 [main] OrderFormTest - json: {"id":"123_ID","accuracy":94.77,"customerNumber":"123_CUSTOMER","orders":[{"accuracy":0.0,"orderNumber":{"accuracy":10.0,"number":123456789},"orderSize":{"accuracy":99.99,"size":"38/40"},"orderAmount":{"accuracy":100.0,"amount":7},"orderPrice":{"accuracy":50.0,"price":999.99},"orderPage":{"accuracy":23.29343,"page":100}},{"accuracy":0.0,"orderNumber":{"accuracy":10.0,"number":123456789},"orderSize":{"accuracy":99.99,"size":"38/40"},"orderAmount":{"accuracy":100.0,"amount":7},"orderPrice":{"accuracy":50.0,"price":999.99},"orderPage":{"accuracy":23.29343,"page":100}}]}

为什么会这样?

【问题讨论】:

  • Java 中的默认等于只需检查参考。数据类为您生成等于。但是你这里的不是数据类

标签: kotlin jackson


【解决方案1】:

问题不在于继承 VS 没有继承本身

在一种情况下,您使用的是data class(它会自动生成equals() 方法),而在另一种情况下,您使用的是标准的class,它没有任何魔力。

在标准类中,你需要自己实现equals()(或者在你的IDE的帮助下生成它)。

【讨论】:

  • 那我想用数据类但是继承好像不行?!
  • 解决此问题的一种方法是将Classification 改为一个接口。
  • 那行得通。谢谢!即使我不喜欢这样,我也必须覆盖变量。在我看来,即使两次声明它们也很奇怪。
  • 我相信您应该能够从抽象类扩展数据类。
  • @r2rek 是的,这是可能的,但 OP 需要将抽象类的属性设为 open 并在数据类中覆盖它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-08
  • 2018-12-12
  • 2016-11-20
  • 1970-01-01
相关资源
最近更新 更多