fastjson在从json字符串解析成对象的时候是不支持多态的。
什么意思呢?就是说我调用JSON.parseObject(jsonstr, XXX.class)方法的时候,如果XXX是一个抽象类,或者接口,我是没有办法根据json字符串中提供的实现类信息解析成相应的实现类的。这样调用后的结果是null。
如何做到对多态的支持呢?我们先要研究一下fastjson的源码。我做的扩展是基于最新版本fastjson-1.1.28.jar进行的。
源码分析
解析的类从JSON转交给DefaultJSONParser
我们调用JSON.parseObject(jsonstr, XXX.class)方法的时候,最后会调用一个parseObject(String input, Type clazz, ParserConfig config, int featureValues, Feature... features)方法。在这个方法中,关键是实例化了一个DefaultJSONParser实例,这个是解析的关键。调用的是parser.parseObject(clazz)。
public static final <T> T parseObject(String text, Class<T> clazz) {
//feature可以new Feature[0]这样生成
return parseObject(text, clazz, new Feature[0]);
}
public static final <T> T parseObject(String text, Class<T> clazz,
Feature... features) {
//最终调用的是该方法
return (T) parseObject(text, (Type) clazz,
ParserConfig.getGlobalInstance(), DEFAULT_PARSER_FEATURE,
features);
}
public static final <T> T parseObject(String input, Type clazz,
ParserConfig config, int featureValues, Feature... features) {
if (input == null) {
return null;
}
for (Feature featrue : features) {
featureValues = Feature.config(featureValues, featrue, true);
}
//解析工作转交给DefaultJSONParser
DefaultJSONParser parser = new DefaultJSONParser(input, config,
featureValues);
T value = (T) parser.parseObject(clazz);
handleResovleTask(parser, value);
parser.close();
return (T) value;
}
解析的真正工作者,各种Deserializer
在DefaultJSONParser的parseObject中,通过ParserConfig去获得相应的反序列化类,并通过反序列化类去反序列化出我们需要解析的对象。
public <T> T parseObject(Type type) {
if (lexer.token() == JSONToken.NULL) {
lexer.nextToken();
return null;
}
//通过ParserConfig去获得反序列化工具类
ObjectDeserializer derializer = config.getDeserializer(type);
try {
//通过反序列化工具类解析出我们需要的对象
return (T) derializer.deserialze(this, type, null);
} catch (JSONException e) {
throw e;
} catch (Throwable e) {
throw new JSONException(e.getMessage(), e);
}
}
ParserConfig是如何管理Deserializer的
常用类的Deserializer保存在IdentityHashMap之中
我们先从ParserConfig的构造器看起,其中向类型为HashSet<Class<?>>的primitiveClasses成员变量添加了各种常用类。向类型为IdentityHashMap<Type, ObjectDeserializer>的derializers成员变量绑定常用类的Deserializer。
private final Set<Class<?>> primitiveClasses = new HashSet<Class<?>>();
private final IdentityHashMap<Type, ObjectDeserializer> derializers = new IdentityHashMap<Type, ObjectDeserializer>();
public ParserConfig(){
primitiveClasses.add(boolean.class);
primitiveClasses.add(Boolean.class);
primitiveClasses.add(char.class);
primitiveClasses.add(Character.class);
primitiveClasses.add(byte.class);
primitiveClasses.add(Byte.class);
primitiveClasses.add(short.class);
primitiveClasses.add(Short.class);
primitiveClasses.add(int.class);
primitiveClasses.add(Integer.class);
primitiveClasses.add(long.class);
primitiveClasses.add(Long.class);
primitiveClasses.add(float.class);
primitiveClasses.add(Float.class);
primitiveClasses.add(double.class);
primitiveClasses.add(Double.class);
primitiveClasses.add(BigInteger.class);
primitiveClasses.add(BigDecimal.class);
primitiveClasses.add(String.class);
primitiveClasses.add(java.util.Date.class);
primitiveClasses.add(java.sql.Date.class);
primitiveClasses.add(java.sql.Time.class);
primitiveClasses.add(ja