Json使用Jackson实现子类多态

本文介绍如何使用Jackson库实现Java对象的JSON序列化和反序列化,特别是针对多态类型的处理方法。通过两种不同方式实现子类类型的识别:全局DefaultTyping机制和在类上使用@JsonTypeInfo注解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目的: Json序列化/反序列化不需要知道具体子类的类型,只需要根据父类以及类别标识就能准确判断子类类型。

方式一:全局Default Typing机制

1
2
objectMapper.enableDefaultTyping(); // default to using DefaultTyping.OBJECT_AND_NON_CONCRETE
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

方式二: 为Class添加@JsonTypeInfo

方式一是全局的方式,会导致序列化后的json结构改变,比如原来的{"prop":"val"}会变成["@class":"class类型",{"prop":"val"}]

而方式二仅在类里新加一个属性,不会破坏json的结构,因此这里采用方式二。

大多数文献都是采用直接在类里写注解的方式,比如:

@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
class Animal { } 

这里采用在jaxb xsd中加注解的方式实现。


<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://bill.com/data" xmlns="http://bill.com/data"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.1"
    xmlns:annox="http://annox.dev.java.net"
    xmlns:ja="http://annox.dev.java.net/org.codehaus.jackson.annotate"
    jaxb:extensionBindingPrefixes="annox">
    
    <xsd:complexType name="BaseClass" abstract="true">
    	<xsd:annotation>
            <xsd:appinfo>
                <annox:annotate>                    
                     <ja:JsonTypeInfo use="CLASS" include="PROPERTY" property="@class"/>
                </annox:annotate>                
            </xsd:appinfo>
        </xsd:annotation>
    </xsd:complexType>
    
    <xsd:complexType name="SubClass">
   		<xsd:complexContent>
	    	<xsd:extension base="BaseClass">
	    		<xsd:sequence>
		        	<xsd:element name="prop1" type="xsd:string" />
		        	<xsd:element name="prop2" type="xsd:string" />
		        </xsd:sequence>
	    	</xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
</xsd:schema>

生成的java类如下:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BaseClass")
@XmlSeeAlso({
    SubClass.class
})
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "@class", include = JsonTypeInfo.As.PROPERTY)
public abstract class BaseClass
    implements Serializable
{

    private final static long serialVersionUID = 1L;

}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "SubClass", propOrder = {
    "prop1",
    "prop2"
})
public class SubClass
    extends BaseClass
    implements Serializable
{

    private final static long serialVersionUID = 1L;
    @XmlElement(required = true)
    protected String prop1;
    @XmlElement(required = true)
    protected String prop2;

    /**
     * 获取prop1属性的值。
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getProp1() {
        return prop1;
    }

    /**
     * 设置prop1属性的值。
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setProp1(String value) {
        this.prop1 = value;
    }

    /**
     * 获取prop2属性的值。
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getProp2() {
        return prop2;
    }

    /**
     * 设置prop2属性的值。
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setProp2(String value) {
        this.prop2 = value;
    }


pom.xml中的关键配置:

<dependency>
      <groupId>org.codehaus.jackson</groupId>
      <artifactId>jackson-core-asl</artifactId>
      <version>1.9.2</version>
</dependency>

<plugins>
	<plugin>
	    <groupId>org.jvnet.jaxb2.maven2</groupId>
	    <artifactId>maven-jaxb2-plugin</artifactId>
	    <configuration>
		<source>1.6</source>
		<target>1.6</target>
		<encoding>UTF-8</encoding>
		<args>
                      <arg>-Xannotate</arg>
                </args>
                <plugins>
                      <plugin>
                            <groupId>org.jvnet.jaxb2_commons</groupId>
                            <artifactId>jaxb2-basics-annotate</artifactId>
                            <version>0.6.3</version>
                      </plugin>
                      <plugin>
                            <groupId>org.jvnet.jaxb2_commons</groupId>
                            <artifactId>jaxb2-basics</artifactId>
                            <version>0.6.3</version>
                      </plugin>                               
                </plugins>
	    </configuration>
	    <dependencies>
	         <dependency>
			<groupId>org.codehaus.jackson</groupId>
			<artifactId>jackson-core-asl</artifactId>
			<version>1.9.2</version>
		</dependency>
            </dependencies>
	</plugin>
</plugins>



然后构造一个Jackson的工具类:

public class JacksonUtil {
	public static String bean2Json(Object obj) {
		ObjectMapper mapper = new ObjectMapper();
//		mapper.enableDefaultTyping();
//		mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

		try {
			return mapper.writeValueAsString(obj);
		}  catch (Exception e) {
            e.printStackTrace();
        }
		return null;
    }
	
	 public static <T> T json2Bean(String json, Class<T> klass) {
		 ObjectMapper mapper = new ObjectMapper();
		 try {
			return mapper.readValue(json, klass);
		} catch (Exception e) {
            e.printStackTrace();
        }
		 return null;
	    }

测试代码:

SubClass sub1 = new SubClass();
sub1.setProp1("testing");
BaseClass base = sub1;
String json = JacksonUtil.bean2Json(base);
System.out.println("serialize: " + json);
BaseClass base2 = JacksonUtil.json2Bean(json, BaseClass.class);
SubClass sub2 = (SubClass) base2;
System.out.println("deserialize: " + sub2.getProp1());

输出结果如下:

22:36:52,974 INFO  [stdout] (http--0.0.0.0-8080-11) serialize: {"@class":"com.bill.data.SubClass","prop1":"testing","prop2":null}
22:36:52,979 INFO  [stdout] (http--0.0.0.0-8080-11) deserialize: testing

参考文献:

http://codelife.me/blog/2012/11/03/jackson-polymorphic-deserialization/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值