java对象中的多态_java-具有嵌套在对象中的type属性的Jackson多态反序列化

如果您查看Jackson Api,则AsPropertyTypeDeserializer是负责使用属性标识子类型的类.如果您查看该类,则有一个名为deserializeTypedFromObject的方法,该方法将使用JsonTypeIdResolver标识子类.我们可以扩展此类,并覆盖deserializeTypedFromObject和forProperty方法.

package com.dilipkumarg.tutorials.dynamicsubtype;

import java.io.IOException;

import com.fasterxml.jackson.core.JsonParser;

import com.fasterxml.jackson.databind.BeanProperty;

import com.fasterxml.jackson.databind.DeserializationContext;

import com.fasterxml.jackson.databind.JavaType;

import com.fasterxml.jackson.databind.JsonDeserializer;

import com.fasterxml.jackson.databind.JsonNode;

import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;

import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;

import com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer;

import com.fasterxml.jackson.databind.node.TreeTraversingParser;

import com.fasterxml.jackson.databind.type.SimpleType;

public class CustomTypeDeserializer extends AsPropertyTypeDeserializer {

public CustomTypeDeserializer(

final JavaType bt, final TypeIdResolver idRes,

final String typePropertyName, final boolean typeIdVisible, final Class> defaultImpl) {

super(bt, idRes, typePropertyName, typeIdVisible, defaultImpl);

}

public CustomTypeDeserializer(

final AsPropertyTypeDeserializer src, final BeanProperty property) {

super(src, property);

}

@Override

public TypeDeserializer forProperty(

final BeanProperty prop) {

return (prop == _property) ? this : new CustomTypeDeserializer(this, prop);

}

@Override

public Object deserializeTypedFromObject(

final JsonParser jp, final DeserializationContext ctxt) throws IOException {

JsonNode node = jp.readValueAsTree();

Class> subType = findSubType(node);

JavaType type = SimpleType.construct(subType);

JsonParser jsonParser = new TreeTraversingParser(node, jp.getCodec());

if (jsonParser.getCurrentToken() == null) {

jsonParser.nextToken();

}

/* 16-Dec-2010, tatu: Since nominal type we get here has no (generic) type parameters,

* we actually now need to explicitly narrow from base type (which may have parameterization)

* using raw type.

*

* One complication, though; can not change 'type class' (simple type to container); otherwise

* we may try to narrow a SimpleType (Object.class) into MapType (Map.class), losing actual

* type in process (getting SimpleType of Map.class which will not work as expected)

*/

if (_baseType != null && _baseType.getClass() == type.getClass()) {

type = _baseType.narrowBy(type.getRawClass());

}

JsonDeserializer deser = ctxt.findContextualValueDeserializer(type, _property);

return deser.deserialize(jsonParser, ctxt);

}

protected Class> findSubType(JsonNode node) {

Class extends ParentClass> subType = null;

String cat = node.get("header").get("category").asText();

if (cat.equals("CATEGORY1")) {

subType = Category1Class.class;

} else if (cat.equals("CATEGORY2")) {

subType = Category2Class.class;

}

return subType;

}

}

在扩展类中,我们绕过了使用idResolver的子类型标识,而是使用标头字段的category字段动态标识.

我们需要TypeResolverBuilder来创建新的CustomTypeDeserializer实例.

package com.dilipkumarg.tutorials.dynamicsubtype;

import java.util.Collection;

import com.fasterxml.jackson.databind.DeserializationConfig;

import com.fasterxml.jackson.databind.JavaType;

import com.fasterxml.jackson.databind.jsontype.NamedType;

import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;

import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;

public class CustomTypeResolver extends StdTypeResolverBuilder {

@Override

public TypeDeserializer buildTypeDeserializer(final DeserializationConfig config, final JavaType baseType, final Collection subtypes) {

return new CustomTypeDeserializer(baseType, null,

_typeProperty, _typeIdVisible, _defaultImpl);

}

}

现在我们有了一个用于子类型识别的CustomTypeResolver,但是当Jackon找到“ ParentClass”时,如何知道该类的外观呢?

我们可以通过两种方式做到这一点:

>使用自定义配置扩展JackonAnnotationInterceptor,并在创建ObjectMapper时对其进行配置.

>使用@JsonTypeResolver批注.这是推荐的方法,因为我们不需要配置任何东西.

包含类型解析器后,我们新的ParentClass类将是:

package com.dilipkumarg.tutorials.dynamicsubtype;

import com.fasterxml.jackson.annotation.JsonTypeInfo;

import com.fasterxml.jackson.databind.annotation.JsonTypeResolver;

@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)

@JsonTypeResolver(CustomTypeResolver.class)

public class ParentClass {

private Header header;

private String nextField;

...

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值