2

您的问题 我已经检查了问题和文档,但找不到解决方案。

以下代码正确地将对象 ( Component) 序列化为字符串,但从字符串反序列化回实例的实例Component不起作用。

有什么建议如何在不取消代表团的情况下做到这一点?

谢谢 :)


import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonSubTypes.Type
import com.fasterxml.jackson.annotation.JsonTypeInfo
import com.fasterxml.jackson.core.json.JsonReadFeature
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.json.JsonMapper
import com.fasterxml.jackson.module.kotlin.KotlinModule
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type"
)
@JsonSubTypes(
    value = [
        Type(value = Space::class, name = Space.TYPE),
        Type(value = Command::class, name = Command.TYPE),
    ]
)
interface Component {
    var id: String

    @get:JsonIgnore
    val type: String
}

data class Command(
    val value: String,
    val component: Component
) : Component by component {
    override val type: String
        get() = TYPE

    companion object {
        const val TYPE = "command"
    }
}

data class Space(
    val space: String,
    private val component: Component
) : Component by component {
    override val type: String
        get() = TYPE

    companion object {
        const val TYPE = "space"
    }
}

data class Info(
    override var id: String,
    override val type: String = "",
) : Component

class FooTest {
    //    private val objectMapper = ObjectMapperFactory.createObjectMapper(emptyList())
    private val objectMapper = JsonMapper.builder()
        .addModule(KotlinModule())
        .serializationInclusion(JsonInclude.Include.NON_NULL)
        .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
        .enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)
        .enable(JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER)
        .build()

    @Test
    fun `should deserialize`() {

        val value = objectMapper.writeValueAsString(
            Command(
                value = "text",
                component = Info(id = "d")
            )
        )

        val obj = objectMapper.readValue(value, Component::class.java)
        assertThat(value).isEqualTo(obj)
    }
}

错误


com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'Info' as a subtype of `<>.<>.<>.<>.jackson.Component`: known type ids = [command, space] (for POJO property 'component')
 at [Source: (String)"{"type":"command","value":"text","component":{"type":"Info","id":"d"},"id":"d"}"; line: 1, column: 54] (through reference chain: <>.<>.<>.<>.jackson.Command["component"])
4

1 回答 1

0

稍微更改了您的代码以修复反序列化,因为它在创建 Info 组件时失败,因为它不在已知JsonSubTypes列表中。

  1. 覆盖 Info 类的类型字段
data class Info(
    override var id: String,
    override val type: String = "info",
) : Component
  1. 将其添加到JsonSubTypes注释中:
@JsonSubTypes(
     value = [
         Type(value = Space::class, name = Space.TYPE),
         Type(value = Command::class, name = Command.TYPE),
         Type(value = Info::class, name = "info"),
     ]
 )
 interface Component

测试代码中的小修复:

        val before = Command(
            value = "text",
            component = Info(id = "d")
        )
        val asString = objectMapper.writeValueAsString(before)

        val after = objectMapper.readValue(asString, Component::class.java)
        assertThat(after).isEqualTo(before)
于 2021-06-27T10:31:45.860 回答