简体   繁体   English

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

[英]Deserialize JSON with Jackson with complex Polymorphic structure

I need help, here is the description of the task: 我需要帮助,这里是任务的描述:
1. I have base interface 我有基本界面

interface IPolymorphicModel

2. I have few nested interfaces: 2.我有几个嵌套的接口:

interface IContentItem extends IPolymorphicModel
interface IAttachment extends IPolymorphicModel

3. I have few implementations: 我的实现很少:

public class MediaAttachment implements IAttachment

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

I am using jackson (also I tried Gson using registerTypeAdapterFactory ) to parse current json structure. 我正在使用jackson(我也使用registerTypeAdapterFactory尝试使用Gson )来解析当前的json结构。 I am using next approach for deserializing json using single Deserializer for all nested items: 我正在使用下一种方法为所有嵌套项使用单个反序列化器反序列化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);
})

But there is the problem with parsing inner items: as you can see inner object can contain object with the same super , and when jackson try to parse them it doesn't know anything about IPolymorphicModel and registering the same BeanDeserializerModifier is not possible because it will cause stack overflow. 但是解析内部项有问题:因为你可以看到内部对象可以包含具有相同super对象,并且当jackson尝试解析它们时它不知道关于IPolymorphicModel任何内容并且注册相同的BeanDeserializerModifier是不可能的,因为它将导致堆栈溢出。

I found the solution. 我找到了解决方案。 And its quite easy at least in this case. 至少在这种情况下它很容易。 To solve such kind of task, you need to use jackson TypeIdResolver . 要解决此类任务,您需要使用jackson TypeIdResolver Here is an example: 这是一个例子:

1. First you need to annotate your base class, where modelType your field by which you can identify, which exactly child of base class you are using: 1.首先,您需要注释基类,其中modelType是您可以识别的字段,您正在使用的基类的子类:

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

2. Implement your own IdResolver.class : 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;
    }
}
  1. In two previous steps we configure jackson to call the same deserialize behaviour for all nested classes of IPolymorphic , so the last step - we need to register deserializer for IPolymorphic : 在之前的两个步骤中,我们配置jackson为所有嵌套的IPolymorphic类调用相同的反序列化行为,所以最后一步 - 我们需要为IPolymorphic注册反序列化器:

     public void configureJackson() { ObjectMapper objectMapper = new ObjectMapper(); Module module = new SimpleModule(); module.addDeserializer(IPolymorphic.class, new PolymorphicJsonDeserializer()); objectMapper.registerModule(module); } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM