Data Binding第二种应用是Full Data Binding.也就是可以支持自定义的Java类到JSON对象的互相转换。
下面的代码演示了简单的使用方法:
类Response的定义:
import lombok.Getter;
import lombok.Setter;
/**
*
* @author chenshu
*/
public class Response {
@Getter @Setter
private String status;
@Getter @Setter
private String message;
}
调用代码:
public class App {
public static void main( String[] args ) throws IOException {
ObjectMapper mapper = new ObjectMapper(); // create once, reuse
String jsonSource = "{\"message\":\"Login succeeded!\",\"status\":null}";
Response response = mapper.readValue(jsonSource, Response.class);
String result = mapper.writeValueAsString(response);
}
}
先通过命令mvn dependency:sources获取源代码。然后就可以调试进入代码观察。
readValue方法内部代码如下:
@SuppressWarnings("unchecked")
public <T> T readValue(String content, Class<T> valueType)
throws IOException, JsonParseException, JsonMappingException
{
// !!! TODO
// _setupClassLoaderForDeserialization(valueType);
return (T) _readMapAndClose(_jsonFactory.createJsonParser(content), _typeFactory.constructType(valueType));
}
_typeFactory.constructType(valueType)使用参数Response.class创建一个SimpleType对象(JavaType的子类),创建时有一个LinkedHashMap对象做的缓存,如果已经创建过,则不再重复创建,取出来直接使用,因此还用到了多线程锁。参考TypeFactory.java里面的代码:
/**
* @param context Mapping of formal parameter declarations (for generic
* types) into actual types
*/
protected JavaType _fromClass(Class<?> clz, TypeBindings context)
{
// Very first thing: small set of core types we know well:
if (clz == String.class) return CORE_TYPE_STRING;
if (clz == Boolean.TYPE) return CORE_TYPE_BOOL;
if (clz == Integer.TYPE) return CORE_TYPE_INT;
if (clz == Long.TYPE) return CORE_TYPE_LONG;
// Barring that, we may have recently constructed an instance:
ClassKey key = new ClassKey(clz);
JavaType result;
synchronized (_typeCache) {
result = _typeCache.get(key);
}
if (result != null) {
return result;
}
// If context was needed, weed do:
/*
if (context == null) {
context = new TypeBindings(this, cls);
}
*/
// First: do we have an array type?
if (clz.isArray()) {
result = ArrayType.construct(_constructType(clz.getComponentType(), null), null, null);
/* Also: although enums can also be fully resolved, there's little
* point in doing so (T extends Enum<T>) etc.
*/
} else if (clz.isEnum()) {
result = new SimpleType(clz);
/* Maps and Collections aren't quite as hot; problem is, due
* to type erasure we often do not know typing and can only assume
* base Object.
*/
} else if (Map.class.isAssignableFrom(clz)) {
result = _mapType(clz);
} else if (Collection.class.isAssignableFrom(clz)) {
result = _collectionType(clz);
} else {
result = new SimpleType(clz);
}
synchronized (_typeCache) {
_typeCache.put(key, result);
}
return result;
}
我没有进一步跟踪,但是推测后面将利用Response.class.getMethods()获得并调用Response的setStatus和setMessage方法。
再看看调用代码:
return (T) _readMapAndClose(_jsonFactory.createJsonParser(content), _typeFactory.constructType(valueType));
_jsonFactory.createJsonParser(content)创建了Jackson Streaming库里面的JsonParser对象。
_jsonFactory.createJsonParser(content)
下面代码来自于Streaming库的JsonFactory.java
/**
* Method for constructing parser for parsing
* contents of given String.
*/
public JsonParser createJsonParser(String content)
throws IOException, JsonParseException
{
Reader r = new StringReader(content);
// true -> we own the Reader (and must close); not a big deal
IOContext ctxt = _createContext(r, true);
// [JACKSON-512]: allow wrapping with InputDecorator
if (_inputDecorator != null) {
r = _inputDecorator.decorate(ctxt, r);
}
return _createJsonParser(r, ctxt);
}
这里只是大概了解一下用到了StringReader读取JSON字符串。因为属于Streaming库的内容,先放一放。
真正从JSON字符串读取对象需要用到叫做反序列化对象的东西,这个东西也是只创建一次,然后缓存。
ObjectMapper.java类里面的代码如下:
/**
* Method called to locate deserializer for the passed root-level value.
*/
protected JsonDeserializer<Object> _findRootDeserializer(DeserializationContext ctxt,
JavaType valueType)
throws JsonMappingException
{
// First: have we already seen it?
JsonDeserializer<Object> deser = _rootDeserializers.get(valueType);
if (deser != null) {
return deser;
}
// Nope: need to ask provider to resolve it
deser = ctxt.findRootValueDeserializer(valueType);
if (deser == null) { // can this happen?
throw new JsonMappingException("Can not find a deserializer for type "+valueType);
}
_rootDeserializers.put(valueType, deser);
return deser;
}
_rootDeserializers 变量类型是ConcurrentHashMap<JavaType, JsonDeserializer<Object>>,因此也是线程安全的。
结论:
1.每个自定义类型,都只会创建一个JavaType(其实是子类SimpleType),并缓存在LinkedHashMap变量中。该缓存变量位于ObjectMapper对象的TypeFactory变量中。
2.每个自定义类型都只有一个反序列化解析器,缓存在ConcurrentHashMap<JavaType, JsonDeserializer<Object>>变量中,该缓存变量是ObjectMapper的变量。
3.为了保证效率,要尽可能的只使用一个ObjectMapper对象。由于1和2的缓存读取和更新都是线程安全的,其他的代码也是线程安全,因此在多线程环境下使用一个ObjectMapper对象也是安全的。