java - 使用具有复杂多态结构的 Jackson 反序列化 JSON

标签 java json jackson polymorphism deserialization

我需要帮助,这是任务的描述:
1.我有基本接口(interface)

interface IPolymorphicModel

2.我有几个嵌套接口(interface):

interface IContentItem extends IPolymorphicModel
interface IAttachment extends IPolymorphicModel

3.我有一些实现:

public class MediaAttachment implements IAttachment

public class Article implements IContentItem {
private List<IAttachment> attachements;
}

我正在使用 jackson(我也尝试使用 registerTypeAdapterFactory 来解析当前的 json 结构。我正在使用下一种方法对所有嵌套项目使用单个反序列化器来反序列化 json:

Module module = new SimpleModule()
module.setDeserializerModifier(new BeanDeserializerModifier() {
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config,
                                 BeanDescription beanDesc,
                                 JsonDeserializer<?> deserializer){
if (IPolymorphicModel.class.isAssignableFrom(beanDesc.getBeanClass())){
   return new PolymorphicJsonDeserializer()
}
return super.modifyDeserializer(config, beanDesc, deserializer);
})

但是解析内部项存在问题:正如您所看到的,内部对象可以包含具有相同 super 的对象,并且当 jackson 尝试解析它们时,它不知道有关 IPolymorphicModel 的任何信息,并且注册相同的 BeanDeserializerModifier 是不可能的,因为这会导致堆栈溢出。

最佳答案

我找到了解决方案。至少在这种情况下它很容易。要解决此类任务,您需要使用 jackson TypeIdResolver。这是一个例子:

1. 首先,您需要注释您的基类,其中 modelType 您可以通过它来识别您正在使用的基类的子级的字段:

@JsonTypeInfo(use = JsonTypeInfo.Id.CUSTOM,
        include = JsonTypeInfo.As.PROPERTY,
        property = "modelType")
@JsonTypeIdResolver(IdResolver.class)
interface IPolymorphic

2.实现您自己的 IdResolver.class:

public class IdResolver implements TypeIdResolver {

    private JavaType baseType = null;

    @Override
    public void init(JavaType baseType) {
        this.baseType = baseType;
    }

    @Override
    public String idFromValue(Object value) {
        return idFromValueAndType(value, value.getClass());
    }

    @Override
    public String idFromValueAndType(Object value, Class<?> suggestedType) {
        String id = "";
        for (Map.Entry<String, Class<? extends IPolymorphic>> entry : PolymorphicTypeRegistry.Companion.getInstance().getMap().entrySet()) {
            if (entry.getValue() == suggestedType) return entry.getKey();
        }        
        return id;
    }

    @Override
    public String idFromBaseType() {
        return idFromValueAndType(null, baseType.getRawClass());
    }

    @Override
    public JavaType typeFromId(String id) {
        Class clazz = PolymorphicTypeRegistry.Companion.getInstance().get(id);
        JavaType javaType = TypeFactory.defaultInstance().constructSpecializedType(baseType, clazz);
        return javaType;
    }

    @Override
    public JavaType typeFromId(DatabindContext context, String id) {
        return typeFromId(id);
    }

    @Override
    public String getDescForKnownTypeIds() {
        return "";
    }

    @Override
    public JsonTypeInfo.Id getMechanism() {
        return JsonTypeInfo.Id.CUSTOM;
    }
}
  • 在前面的两个步骤中,我们将 jackson 配置为对 IPolymorphic 的所有嵌套类调用相同的反序列化行为,因此最后一步 - 我们需要为 IPolymorphic 注册反序列化器:

    public void configureJackson() {
        ObjectMapper objectMapper = new ObjectMapper();
        Module module = new SimpleModule();
        module.addDeserializer(IPolymorphic.class, new PolymorphicJsonDeserializer());
        objectMapper.registerModule(module);
    }
    
  • 关于java - 使用具有复杂多态结构的 Jackson 反序列化 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41849708/

    相关文章:

    java - cucumber - java.lang.NoClassDefFoundError

    json - 在dart中按字母顺序对对象的JSON数组以及属性的 bool 值进行排序

    javascript - 处理未知格式的 JSON

    java - Jackson 功能 ACCEPT_SINGLE_VALUE_AS_ARRAY 不适用于注释

    java - Spring Boot 中 OffsetDateTime 的 jackson 日期格式

    Java SQL "ERROR: Relation "表名“不存在”

    java - 在 Ubuntu 19.10 中找不到 Oracle JDK 8 Keytool

    python - 使用python打印嵌套在数组中的json对象

    java - 如何防止ObjectMapper转换转义的unicode?

    java - 有 JGit 管道 API 吗?