实例解析Json反序列化之ObjectMapper(自定义实现反序列化方法)
|
对于服务器端开发人员而言,调用第三方接口获取数据,将其“代理”转化并返给客户端几乎是家常便饭的事儿。 一般情况下,第三方接口返回的数据类型是json格式,而服务器开发人员则需将json格式的数据转换成对象,继而对其进行处理并封装,以返回给客户端。 在不是特别考虑效率的情况下(对于搜索、缓存等情形可以考虑使用thrift和protobuffer),通常我们会选取jackson包中的ObjectMapper类对json串反序列化以得到相应对象。通常会选取readValue(String content,Class<T>valueType)方法进行反序列化。 ObjectMapper的readValue方法将json串反序列化为对象的过程大致为: 依据传入的json串和目标对象类型分别创建JsonParse和JavaType,随后生成DeserializationConfig、DeserializationContext、JsonDeserializer,其中JsonDeserializer的实现类决定将要执行哪一种类型解析(Bean、Map、String等),JsonParse中存储了待解析字符串及其它信息,在解析的过程中通过token来判断当前匹配的类型(例如:如果遇到{,将其判断为对象类型的起始位置;遇到[,将其判断为集合类型的起始位置),一旦确定了类型,则跳入与之对应的反序列化类中进行处理,得到结果,然后token往后移动,接着解析下一个串。可以看做类似递归的方式进行解析,当通过token判断为一个对象时,则会跳入BeanDeserializer中进行解析,随后遍历该对象的所有字段,如果字段是字符串,则跳到StringDeserializer中进行解析,如果字段是数组,则跳到CollectionDeserializer中进行解析,直到解析完整个字符串为止。也可以看做类似而树的深度遍历,理解起来还是挺容易的。 下面将简单介绍ObjectMapper的readValue方法进行反序列化的过程: a:通过json串和对象类型得到JsonParser和JavaType。
public <T> T readValue(String content,Class<T> valueType)
throws IOException,JsonParseException,JsonMappingException
{
return (T) _readMapAndClose(_jsonFactory.createParser(content),_typeFactory.constructType(valueType));
}
//获取json解析器,其中包含带解析的串
public JsonParser createParser(String content) throws IOException,JsonParseException {
final int strLen = content.length();
// Actually,let's use this for medium-sized content,up to 64kB chunk (32kb char)
if (_inputDecorator != null || strLen > 0x8000 || !canUseCharArrays()) {
// easier to just wrap in a Reader than extend InputDecorator; or,if content
// is too long for us to copy it over
return createParser(new StringReader(content));
}
IOContext ctxt = _createContext(content,true);
char[] buf = ctxt.allocTokenBuffer(strLen);
content.getChars(0,strLen,buf,0);
return _createParser(buf,ctxt,true);
}
//将待解析的类型转化为JavaType类型
public JavaType constructType(Type type) {
return _constructType(type,null);
}
protected JavaType _constructType(Type type,TypeBindings context)
{
JavaType resultType;
// simple class?
if (type instanceof Class<?>) {
resultType = _fromClass((Class<?>) type,context);
}
// But if not,need to start resolving.
else if (type instanceof ParameterizedType) {
resultType = _fromParamType((ParameterizedType) type,context);
}
else if (type instanceof JavaType) { // [Issue#116]
return (JavaType) type;
}
else if (type instanceof GenericArrayType) {
resultType = _fromArrayType((GenericArrayType) type,context);
}
else if (type instanceof TypeVariable<?>) {
resultType = _fromVariable((TypeVariable<?>) type,context);
}
else if (type instanceof WildcardType) {
resultType = _fromWildcard((WildcardType) type,context);
} else {
// sanity check
throw new IllegalArgumentException("Unrecognized Type: "+((type == null) ? "[null]" : type.toString()));
}
if (_modifiers != null && !resultType.isContainerType()) {
for (TypeModifier mod : _modifiers) {
resultType = mod.modifyType(resultType,type,context,this);
}
}
return resultType;
}
b、获取反序列化配置对象和上下文对象,进行第一步的序列化操作。
protected Object _readMapAndClose(JsonParser jp,JavaType valueType)
throws IOException,JsonMappingException
{
try {
Object result;
DeserializationConfig cfg = getDeserializationConfig();
DeserializationContext ctxt = createDeserializationContext(jp,cfg);
//依据valueType得到反序列化的解析器
// 对象对应的是beanDeserializer map对应的是MapDeserializer 。。。。
JsonDeserializer<Object> deser = _findRootDeserializer(ctxt,valueType);
if (cfg.useRootWrapping()) {
result = _unwrapAndDeserialize(jp,cfg,valueType,deser);
} else {
//如果是对象,则调到BeanDeserializer类中进行解析
result = deser.deserialize(jp,ctxt);
}
ctxt.checkUnresolvedObjectId();
}
// Need to consume the token too
jp.clearCurrentToken();
return result;
} finally {
try {
jp.close();
} catch (IOException ioe) { }
}
}
c、跳入到BeanDeserializer类中。
下面以BeanDeserializer为例进行讲解:
@Override
public Object deserialize(JsonParser p,DeserializationContext ctxt)
throws IOException
{
JsonToken t = p.getCurrentToken();
// common case first
if (t == JsonToken.START_OBJECT) { // TODO: in 2.6,use 'p.hasTokenId()'
if (_vanillaProcessing) {
return vanillaDeserialize(p,p.nextToken());
}
p.nextToken();
if (_objectIdReader != null) {
return deserializeWithObjectId(p,ctxt);
}
return deserializeFromObject(p,ctxt);
}
return _deserializeOther(p,t);
}
/**
* Streamlined version that is only used when no "special"
* features are enabled.
*/
private final Object vanillaDeserialize(JsonParser p,DeserializationContext ctxt,JsonToken t)
throws IOException
{
final Object bean = _valueInstantiator.createUsingDefault(ctxt);
// [databind#631]: Assign current value,to be accessible by custom serializers
p.setCurrentValue(bean);
for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
String propName = p.getCurrentName();
p.nextToken();
if (!_beanProperties.findDeserializeAndSet(p,bean,propName)) {
handleUnknownVanilla(p,propName);
}
}
return bean;
}
/**
* Convenience method that tries to find property with given name,and
* if it is found,call {@link SettableBeanProperty#deserializeAndSet}
* on it,and return true; or,if not found,return false.
* Note,too,that if deserialization is attempted,possible exceptions
* are wrapped if and as necessary,so caller need not handle those.
*
* @since 2.5
*/
public boolean findDeserializeAndSet(JsonParser p,Object bean,String key) throws IOException
{
if (_caseInsensitive) {
key = key.toLowerCase();
}
int index = key.hashCode() & _hashMask;
Bucket bucket = _buckets[index];
// Let's unroll first lookup since that is null or match in 90+% cases
if (bucket == null) {
return false;
}
// Primarily we do just identity comparison as keys should be interned
if (bucket.key == key) {
try {
bucket.value.deserializeAndSet(p,bean);
} catch (Exception e) {
wrapAndThrow(e,key,ctxt);
}
return true;
}
return _findDeserializeAndSet2(p,index);
}
MethodProperty
@Override
public void deserializeAndSet(JsonParser jp,Object instance) throws IOException
{
Object value = deserialize(jp,ctxt);
try {
//将得到的结果放入反序列化对应的对象中
_setter.invoke(instance,value);
} catch (Exception e) {
_throwAsIOE(e,value);
}
}
public final Object deserialize(JsonParser p,DeserializationContext ctxt) throws IOException
{
JsonToken t = p.getCurrentToken();
if (t == JsonToken.VALUE_NULL) {
return (_nullProvider == null) ? null : _nullProvider.nullValue(ctxt);
}
if (_valueTypeDeserializer != null) {
return _valueDeserializer.deserializeWithType(p,_valueTypeDeserializer);
}
return _valueDeserializer.deserialize(p,ctxt);
}
//如果继承了JsonDeserializer类重写了deseriakize方法,则会跳转到对应注入的类中进行处理
//不出意外的话最后都会调用 DeserializationContext的readValue(JsonParser p,Class<T> type)方法,然后会根据type的类型跳转到对应的反序列化类中进行处理。
public <T> T readValue(JsonParser p,Class<T> type) throws IOException {
return readValue(p,getTypeFactory().constructType(type));
}
@SuppressWarnings("unchecked")
public <T> T readValue(JsonParser p,JavaType type) throws IOException {
//得到最终解析的类型,Map list string。。。。
JsonDeserializer<Object> deser = findRootValueDeserializer(type);
if (deser == null) {
}
return (T) deser.deserialize(p,this);
}
//例如这里如果是一个map,则会调用MapDeserializer的deserizlize方法得到最后的返回结果。
//对于集合类,会通过token按照顺序解析生成一个个的集合对象并放入集合中。
JsonToken t;
while ((t = p.nextToken()) != JsonToken.END_ARRAY) {
try {
Object value;
if (t == JsonToken.VALUE_NULL) {
value = valueDes.getNullValue();
} else if (typeDeser == null) {
value = valueDes.deserialize(p,ctxt);
} else {
value = valueDes.deserializeWithType(p,typeDeser);
}
if (referringAccumulator != null) {
referringAccumulator.add(value);
} else {
result.add(value);
}
} catch (UnresolvedForwardReference reference) {
if (referringAccumulator == null) {
throw JsonMappingException
.from(p,"Unresolved forward reference but no identity info",reference);
}
Referring ref = referringAccumulator.handleUnresolvedReference(reference);
reference.getRoid().appendReferring(ref);
} catch (Exception e) {
throw JsonMappingException.wrapWithPath(e,result,result.size());
}
}
return result;
(编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
