今天在网上看代码时,发现项目使用了Gson,用于将json字符串转换成javaBean.

以前没使用过Gson,随即,简单入了个们,

想起fastjson也有将json字符串转换成javaBean的API,随即简单比较了下源码.

fastjson中的API如下:

    /**
* @since 1.2.9
*/
public <T> T toJavaObject(Class<T> clazz) {
return TypeUtils.cast(this, clazz, ParserConfig.getGlobalInstance());
} @SuppressWarnings({ "unchecked", "rawtypes" })
public static <T> T cast(Object obj, Class<T> clazz, ParserConfig config) {
if (obj == null) {
return null;
} if (clazz == null) {
throw new IllegalArgumentException("clazz is null");
} if (clazz == obj.getClass()) {
return (T) obj;
} if (obj instanceof Map) {
if (clazz == Map.class) {
return (T) obj;
} Map map = (Map) obj;
if (clazz == Object.class && !map.containsKey(JSON.DEFAULT_TYPE_KEY)) {
return (T) obj;
} return castToJavaBean((Map<String, Object>) obj, clazz, config);
} if (clazz.isArray()) {
if (obj instanceof Collection) { Collection collection = (Collection) obj;
int index = 0;
Object array = Array.newInstance(clazz.getComponentType(), collection.size());
for (Object item : collection) {
Object value = cast(item, clazz.getComponentType(), config);
Array.set(array, index, value);
index++;
} return (T) array;
} if (clazz == byte[].class) {
return (T) castToBytes(obj);
}
} if (clazz.isAssignableFrom(obj.getClass())) {
return (T) obj;
} if (clazz == boolean.class || clazz == Boolean.class) {
return (T) castToBoolean(obj);
} if (clazz == byte.class || clazz == Byte.class) {
return (T) castToByte(obj);
} // if (clazz == char.class || clazz == Character.class) {
// return (T) castToCharacter(obj);
// } if (clazz == short.class || clazz == Short.class) {
return (T) castToShort(obj);
} if (clazz == int.class || clazz == Integer.class) {
return (T) castToInt(obj);
} if (clazz == long.class || clazz == Long.class) {
return (T) castToLong(obj);
} if (clazz == float.class || clazz == Float.class) {
return (T) castToFloat(obj);
} if (clazz == double.class || clazz == Double.class) {
return (T) castToDouble(obj);
} if (clazz == String.class) {
return (T) castToString(obj);
} if (clazz == BigDecimal.class) {
return (T) castToBigDecimal(obj);
} if (clazz == BigInteger.class) {
return (T) castToBigInteger(obj);
} if (clazz == Date.class) {
return (T) castToDate(obj);
} if (clazz == java.sql.Date.class) {
return (T) castToSqlDate(obj);
} if (clazz == java.sql.Timestamp.class) {
return (T) castToTimestamp(obj);
} if (clazz.isEnum()) {
return (T) castToEnum(obj, clazz, config);
} if (Calendar.class.isAssignableFrom(clazz)) {
Date date = castToDate(obj);
Calendar calendar;
if (clazz == Calendar.class) {
calendar = Calendar.getInstance(JSON.defaultTimeZone, JSON.defaultLocale);
} else {
try {
calendar = (Calendar) clazz.newInstance();
} catch (Exception e) {
throw new JSONException("can not cast to : " + clazz.getName(), e);
}
}
calendar.setTime(date);
return (T) calendar;
} if (obj instanceof String) {
String strVal = (String) obj; if (strVal.length() == 0 //
|| "null".equals(strVal) //
|| "NULL".equals(strVal)) {
return null;
} if (clazz == java.util.Currency.class) {
return (T) java.util.Currency.getInstance(strVal);
}
} throw new JSONException("can not cast to : " + clazz.getName());
} @SuppressWarnings({ "unchecked" })
public static <T> T castToJavaBean(Map<String, Object> map, Class<T> clazz, ParserConfig config) {
try {
if (clazz == StackTraceElement.class) {
String declaringClass = (String) map.get("className");
String methodName = (String) map.get("methodName");
String fileName = (String) map.get("fileName");
int lineNumber;
{
Number value = (Number) map.get("lineNumber");
if (value == null) {
lineNumber = 0;
} else {
lineNumber = value.intValue();
}
} return (T) new StackTraceElement(declaringClass, methodName, fileName, lineNumber);
} {
Object iClassObject = map.get(JSON.DEFAULT_TYPE_KEY);
if (iClassObject instanceof String) {
String className = (String) iClassObject; Class<?> loadClazz = (Class<T>) loadClass(className); if (loadClazz == null) {
throw new ClassNotFoundException(className + " not found");
} if (!loadClazz.equals(clazz)) {
return (T) castToJavaBean(map, loadClazz, config);
}
}
} if (clazz.isInterface()) {
JSONObject object; if (map instanceof JSONObject) {
object = (JSONObject) map;
} else {
object = new JSONObject(map);
} return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class<?>[] { clazz }, object);

} if (config == null) {
config = ParserConfig.getGlobalInstance();
} JavaBeanDeserializer javaBeanDeser = null;
ObjectDeserializer deserizer = config.getDeserializer(clazz);
if (deserizer instanceof JavaBeanDeserializer) {
javaBeanDeser = (JavaBeanDeserializer) deserizer;
} if (javaBeanDeser == null) {
throw new JSONException("can not get javaBeanDeserializer");
} return (T) javaBeanDeser.createInstance(map, config);
} catch (Exception e) {
throw new JSONException(e.getMessage(), e);
}
}

  简单捋了一遍,看到代码中标黄的部分代码,可知,是利用反射原理来获得javaBean的.

如下,为Gson的demo:

 package cn.code.gson;

 import java.io.*;

 import java.util.Map;

 import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import cn.code.entity.Person; /**
* Created by zq on 2017/6/16.
*/
public class GsonTest { /**
* @param args 主函数形参
*/
public static void main(String[] args) {
Gson gson = new GsonBuilder().create(); gson.toJson("Hello", System.out);
gson.toJson("123", System.out);
System.out.println(); // try (Writer writer = new FileWriter("d:\\gson.txt")) {
// gson.toJson("Hello", writer);
// gson.toJson("123", writer);
// } catch (IOException e) {
// e.printStackTrace();
// }
FileInputStream fileInputStream = null; try {
fileInputStream = new FileInputStream("d:\\gson.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
} Person person = getJavaBean(fileInputStream); System.out.println(person);
} /**
*
* @param fileInputStream 根据附件字节流 返回java类
* @return
*/
public static Person getJavaBean(FileInputStream fileInputStream) {
Gson gson = new GsonBuilder().create();
Person person = null; try (Reader reader = new InputStreamReader(fileInputStream)) {
person = gson.fromJson(reader, Person.class);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} return person;
}
} //~ Formatted by Jindent --- http://www.jindent.com

Gson中使用了如下代码获取javaBean:

person = gson.fromJson(reader, Person.class);
源码如下(版本:2.2.4):
   public <T> T fromJson(Reader json, Class<T> classOfT) throws JsonSyntaxException, JsonIOException {
JsonReader jsonReader = new JsonReader(json);
Object object = fromJson(jsonReader, classOfT);
assertFullConsumption(object, jsonReader);
return Primitives.wrap(classOfT).cast(object);
} @SuppressWarnings("unchecked")
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
boolean isEmpty = true;
boolean oldLenient = reader.isLenient();
reader.setLenient(true);
try {
reader.peek();
isEmpty = false;
TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
TypeAdapter<T> typeAdapter = getAdapter(typeToken);
T object = typeAdapter.read(reader);
return object;
} catch (EOFException e) {
/*
* For compatibility with JSON 1.5 and earlier, we return null for empty
* documents instead of throwing.
*/
if (isEmpty) {
return null;
}
throw new JsonSyntaxException(e);
} catch (IllegalStateException e) {
throw new JsonSyntaxException(e);
} catch (IOException e) {
// TODO(inder): Figure out whether it is indeed right to rethrow this as JsonSyntaxException
throw new JsonSyntaxException(e);
} finally {
reader.setLenient(oldLenient);
}
}

以上版本中,Json和javabean之间依赖于各类的TypeAdapter(类型转换器集合)获得:

TypeAdapter<?> cached = typeTokenCache.get(type);
if (cached != null) {
return (TypeAdapter<T>) cached;
}
; 以下是版本1.6中的部分核心源码:
private <T> T fromJsonObject(Type typeOfT, JsonObject jsonObject,
JsonDeserializationContext context) throws JsonParseException {
JsonObjectDeserializationVisitor<T> visitor = new JsonObjectDeserializationVisitor<T>(
jsonObject, typeOfT, navigatorFactory, objectConstructor, deserializers, context);
ObjectNavigator on = navigatorFactory.create(new ObjectTypePair(null, typeOfT, true)); //适配器模式
on.accept(visitor);
return visitor.getTarget();
} /**
* Navigate all the fields of the specified object. If a field is null, it
* does not get visited.
*/
public void accept(Visitor visitor) {
TypeInfo objTypeInfo = new TypeInfo(objTypePair.type);
if (exclusionStrategy.shouldSkipClass(objTypeInfo.getRawClass())) {
return;
}
boolean visitedWithCustomHandler = visitor.visitUsingCustomHandler(objTypePair);
if (!visitedWithCustomHandler) {
Object obj = objTypePair.getObject();
Object objectToVisit = (obj == null) ? visitor.getTarget() : obj;
if (objectToVisit == null) {
return;
}
objTypePair.setObject(objectToVisit);
visitor.start(objTypePair);
try {
if (objTypeInfo.isArray()) {
visitor.visitArray(objectToVisit, objTypePair.type);
} else if (objTypeInfo.getActualType() == Object.class
&& isPrimitiveOrString(objectToVisit)
) {
// TODO(Joel): this is only used for deserialization of "primitives"
// we should rethink this!!!
visitor.visitPrimitive(objectToVisit);
objectToVisit = visitor.getTarget();
} else {
visitor.startVisitingObject(objectToVisit);
ObjectTypePair currObjTypePair = objTypePair.toMoreSpecificType();
Class<?> topLevelClass = new TypeInfo(currObjTypePair.type).getRawClass();
for (Class<?> curr = topLevelClass; curr != null && !curr.equals(Object.class); curr =
curr.getSuperclass()) {
if (!curr.isSynthetic()) {
navigateClassFields(objectToVisit, curr, visitor);
}
}
}
} finally {
visitor.end(objTypePair);
}
}
}
private void navigateClassFields(Object obj, Class<?> clazz, Visitor visitor) {
Field[] fields = clazz.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
for (Field f : fields) { //遍历javabean 的field 赋值
FieldAttributes fieldAttributes = new FieldAttributes(clazz, f);
if (exclusionStrategy.shouldSkipField(fieldAttributes)
|| exclusionStrategy.shouldSkipClass(fieldAttributes.getDeclaredClass())) {
continue; // skip
}
TypeInfo fieldTypeInfo = TypeInfoFactory.getTypeInfoForField(f, objTypePair.type);
Type declaredTypeOfField = fieldTypeInfo.getActualType();
boolean visitedWithCustomHandler =
visitor.visitFieldUsingCustomHandler(fieldAttributes, declaredTypeOfField, obj);
if (!visitedWithCustomHandler) {
if (fieldTypeInfo.isArray()) {
visitor.visitArrayField(fieldAttributes, declaredTypeOfField, obj);
} else {
visitor.visitObjectField(fieldAttributes, declaredTypeOfField, obj);
}
}
}

  

以上为粗略了解,甚至不算入门,有兴趣的小伙伴们可自行阅读源码.

												

gson和fastjson将json对象转换成javaBean 简单对照的更多相关文章

  1. json字符串转成 json对象 json对象转换成java对象

    import com.alibaba.fastjson.JSONArray;import com.alibaba.fastjson.JSONObject; 依赖包 <dependency> ...

  2. 前台 JSON对象转换成字符串 相互转换 的几种方式

    在最近的工作中,使用到JSON进行数据的传递,特别是从前端传递到后台,前台可以直接采用ajax的data函数,按json格式传递,后台Request即可,但有的时候,需要传递多个参数,后台使用requ ...

  3. json字符串转换成json对象,json对象转换成字符串,值转换成字符串,字符串转成值

    一.json相关概念 json,全称为javascript object notation,是一种轻量级的数据交互格式.采用完全独立于语言的文本格式,是一种理想的数据交换格式. 同时,json是jav ...

  4. JSON对象转换成JSON字符串

    1.问题背景 有一个json对象,需要将其转换成json字符串 JSON.stringify(obj) 2.实现源码 <!DOCTYPE html PUBLIC "-//W3C//DT ...

  5. json字符串转json对象,json对象转换成java对象

    @RequestMapping(value = "updateInvestorApplyAccountNo", method = RequestMethod.POST) @Resp ...

  6. (转)json格式转换成javaBean对象的方法

    把json格式转换成javaBean才可以.于是查了一下资料,网上最多的资料就是下面的这种方式: Java code? 1 2 3 4 5 6 7 8 9 String str = "[{\ ...

  7. FastJson将Java对象转换成json

    确保环境依赖都配置好! 1.在pom.xml导入依赖 <dependency> <groupId>com.alibaba</groupId> <artifac ...

  8. JSON对象转换成字符串【JSON2.JS】

    下载地址 https://github.com/douglascrockford/JSON-js JSON.JS和JSON2.JS的区别 JSON.JS使用的方法名称不同,用的是toJSONStrin ...

  9. 将JSON对象转换成IList,好用linq

    JObject JToken JProperty IList<> 搞得头都大了,记而备忘: JObject json = ..... JToken[] jps = json["r ...

随机推荐

  1. 【算法】php实现斐波那契数列

    斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21.这个数列从第3项开始,每一项都等于前两项之和. 根据这个定义,斐波那契数列的递推公式是:f(n)=f(n-1)+f(n ...

  2. A.01.01—模块的输入—低端输入

    汽车电子模块的输入一般包含数字量低端输入.数字量高端输入.模拟量输入.脉宽调制输入.总线信号输入.脉冲信号输入,对于无线信号输入和视频信号音频信号我们不做讨论. 数字量低端输入是应用最为广泛的一种输入 ...

  3. Can DBC文件翻译

    1 引言 DBC文件描述单个CAN网络的通信.这个信息足以监测和分析网络并模拟不是物理可用的节点(剩余的总线模拟). DBC文件也可以用来开发电子控制单元的通信软件,该控制单元应该是CAN网络的一部分 ...

  4. [WC2018]州区划分

    [WC2018]州区划分 注意审题: 1.有序选择 2.若干个州 3.贡献是州满意度的乘积 枚举最后一个州是哪一个,合法时候贡献sum[s]^p,否则贡献0 存在欧拉回路:每个点都是偶度数,且图连通( ...

  5. Manjaro下Steam无法启动

    问题描述 直接在桌面环境运行Steam,不会出现任何反应,甚至没有闪过一个对话框. 在终端中运行Sterm,出现以下提示 Repairing installation, linking /home/z ...

  6. 在Vue框架中使用百度地图

    1.首先在index.html中引入百度地图 <script type="text/javascript" src="http://api.map.baidu.co ...

  7. A1142. Maximal Clique

    A clique is a subset of vertices of an undirected graph such that every two distinct vertices in the ...

  8. Python之函数--命名空间、作用域、global、nonlocal、函数的嵌套和作用域链

    命名空间 -------‘’存放名字与值的关系”的空间 代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间: 在函数的运行中开辟的临时的空间叫做局部命名空间. 命名空间一共分为三种: ...

  9. C 线程学习记录

    "互斥锁"(Mutual exclusion,缩写 Mutex),防止多个线程同时读写某一块内存区域. 这时的解决方法,就是在门口挂n把钥匙.进去的人就取一把钥匙,出来时再把钥匙挂 ...

  10. Codeforces Round #523 (Div. 2)

    Codeforces Round #523 (Div. 2) 题目一览表 来源 考察知识点 完成时间 A Coins cf 贪心(签到题) 2018.11.23 B Views Matter cf 思 ...