Jackson输出List,元素多类型没有输出type分析及解决

1. 背景

在使用Jackson序列化一个List对象的时候,偶然发现输出的元素都不带表示类型的type字段。先前这个List作为一个JavaBean的字段,序列化整个Bean时,是带有类型的,但单独序列化List的时候,却不带type,造成反序列化无法找到对应的类型。

构造下面的示例以说明问题。

public class Test
{
	
	@JsonTypeInfo(
		    use = JsonTypeInfo.Id.NAME, // Were binding by providing a name
		    include = JsonTypeInfo.As.PROPERTY, // The name is provided in a property
		    property = "type", // Property name is type
		    visible = true // Retain the value of type after deserialisation
		)
	@JsonSubTypes({//Below, we define the names and the binding classes.
	    @JsonSubTypes.Type(value = Bean.class, name = "Bean") ,
	    @JsonSubTypes.Type(value = Bean0.class, name = "Bean0") 
	})
	static class Bean
	{
		
	}
	
	static class Bean0 extends Bean
	{
		
	}
	
	static class A
	{
		List<Bean> list = CS.arrayList() ;
		public List<Bean> getList()
		{
			return list;
		}
		public void setList(List<Bean> aList)
		{
			list = aList;
		}
	}

	public static void main(String[] args) throws NoSuchMethodException, SecurityException, NoSuchFieldException
	{
		List<Bean> list = CS.arrayList() ;
		list.add(new Bean()) ;
		list.add(new Bean0()) ;
 		JacksonUtils.toString(list) ;
 		System.out.println("List的输出结果:");
 		System.out.println(JacksonUtils.toString(list));
 		
 		A a = new A() ;
 		a.setList(list) ;
 		System.out.println("类A的输出结果:");
 		System.out.println(JacksonUtils.toString(a));
	}

}

输出结果:

List的输出结果:
[{},{}]
类A的输出结果:
{"list":[{"type":"Bean"},{"type":"Bean0"}]}

2. 原因分析

之所以会如此,这和Java的泛型类型擦除机制有关。在一个方法内部声明的List,如下:

List<Bean> list = CS.arrayList() ;
list.add(new Bean()) ;
list.add(new Bean0()) ;

通过反射机制,是无法得知list里面的元素类型是Bean的,因为这里List<Bean>指定的Bean类型会被擦除,对于运行期来说,和List<Object>没有区别。

对于类型A里面的List<Bean> list ;字段来说,它是由额外的记录的,取得方法如下:

ParameterizedType type = (ParameterizedType)A.class.getDeclaredField("list").getGenericType();
System.out.println(type.getRawType()); 
System.out.println(type.getActualTypeArguments()[0]); 

输出结果:

interface java.util.List
class com.cimstech.st.ms.ia.Test$Bean

因为类型被擦除了,所以它在反序列化的时候,不能得知List里面元素的基准类型,它就和List<Object>没有区别,从而无法同步基准类型寻找到@JsonTypeInfo@JsonSubTypes注解上的信息,只能把里面的元素当作JavaBean序列化。

3. 解决办法

List<Bean> list = CS.arrayList() ;
list.add(new Bean()) ;
list.add(new Bean0()) ;
System.out.println("List的输出结果:") ;
System.out.println(JacksonUtils.toString(list , new TypeReference<List<Bean>>(){}));

输出结果:

List的输出结果:
[{"type":"Bean"},{"type":"Bean0"}]

JacksonUtils的toString方法:

public static <T> String toString(Object aBean , TypeReference<T> aTypeReference)
{
	if(aBean == null)
		return null ;
	try
	{
		return getObjectMapper().writerFor(aTypeReference).writeValueAsString(aBean) ;
	}
	catch (JsonProcessingException e)
	{
		throw new JSONException(e) ;
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值