为什么 Jackson 不解析使用相同的 ObjectMapper 序列化的 JSON?

Why does Jackson not parse a JSON serialized with the same ObjectMapper?

提问人:k.meinkopf 提问时间:10/26/2023 最后编辑:k.meinkopf 更新时间:10/27/2023 访问量:56

问:

我正在尝试序列化一些具有大量嵌套属性的大对象(其中很多是多态的)。 就目前而言,我在尝试序列化基本上是空占位符的对象时遇到了一个问题:

class EmptyTagHolder<T> : TagHolder<T> {
    override fun contains(tag: T) = false

    override fun plus(other: TagHolder<T>) = other

    override fun plus(other: T) = TagSet(other)

    override fun iterator() = emptyList<T>().iterator()
}

这是:TagHolder

interface TagHolder<TagType> : Iterable<TagType> {
    operator fun contains(tag: TagType): Boolean
    operator fun plus(other: TagHolder<TagType>): TagHolder<TagType>
    operator fun plus(other: TagType): TagHolder<TagType>
}

可以有其他的实现,这里实际上提到了一个,.但关键是,杰克逊序列化了这样的实例:TagHolderTagSetEmptyTagHolder

{
    "[package].EmptyTagHolder": [ ]
}

我需要在 Redis 中存储我提到的那个大对象,它基本上是一个编辑器状态,从实际数据库中提取成本很高,因此它作为缓存存储在 Redis 中。 当涉及到反序列化该对象时,Jackson 在这件事上失败了,并出现以下错误:EmptyTagHolder

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `[package].EmptyTagHolder<[package].EntityTag>` from Array value (token `JsonToken.START_ARRAY`)

所以问题是:我如何让杰克逊实际消耗它之前产生的字节?

更新: 包含以下属性的类:TagHolder

interface Entity {
    val id: SourceAwareIdentifier

    val type: EntityType

    val tags: TagHolder<EntityTag>
    val adjacencyTags: TagHolder<EntityTag>

    val properties: PropertyStore
}

UPD2: 实际类实现:

data class LocalEntity(
    override val id: SourceAwareIdentifier,
    override val type: EntityType,
    override val tags: TagHolder<EntityTag>,
    override val adjacencyTags: TagHolder<EntityTag>,
    override val properties: EditablePropertyStore,
) : Entity

我得到的 json 作为序列化结果:

{
  "entity": {
    "somepackage.data.network.local.model.entity.LocalEntity": {
      "label": "Test",
      "id": {
        "somepackage.data.network.model.id.impl.RawSourceAwareIdentifier": {
          "source": "local",
          "internalId": "local:57fc8745-706e-4159-847f-7a35182d330f"
        }
      },
      "type": {
        "somepackage.data.network.model.entity.EntityType": "Regular"
      },
      "tags": {
        "somepackage.data.generic.impl.TagSet": {
          "tags": {
            "java.util.Collections$SingletonSet": [
              {
                "somepackage.data.network.model.entity.EntityTag": "Lorem"
              }
            ]
          }
        }
      },
      "adjacencyTags": {
        "somepackage.data.generic.impl.EmptyTagHolder": [ ]
      },
      "properties": {
        "somepackage.data.generic.propertystore.impl.BasicEditablePropertyStore": {
          "overlay": {
            "somepackage.data.generic.propertystore.impl.NoopEditablePropertyStoreOverlay": { }
          }
        }
      }
    }
  }
}

JSON Spring Kotlin Redis Jackson

评论

0赞 Jorn 10/26/2023
您应该研究如何使用注释JsonSubTypes
0赞 k.meinkopf 10/27/2023
@Jorn它能对我有什么帮助?在序列化和解析时,它确实正确地识别了类型本身,它只是无法将空数组解析为(根本没有解释,但为什么它首先将其序列化为空数组)。EmptyTagHolder
0赞 Jorn 10/27/2023
两者都没有任何可序列化的属性。你还期望它做什么?我希望 Jackson 除了值是 之外没有什么可继续的,所以它只是写了一个空的可迭代对象。由于您尚未指定特定的子类,因此没有迹象表明您想要反序列化。TagHolderEmptyTagHolderIterableEmptyTagHolder
0赞 k.meinkopf 10/27/2023
@Jorn它实际上在我提供的序列化 JSON 中有一个类型注释。我的 ObjectMapper 实例配置为将每个值的类型显式指定为 。该属性名称不是我定义的。这是由 Jackson 作为类型注释生成的。WRAPPER_OBJECT"[package].EmptyTagHolder"
0赞 Jorn 10/27/2023
也许您可以显示包含 ?我不希望该信息存在于属性密钥中。EmptyTagHolder

答: 暂无答案