Problems
- 如果json中有某个对象不想解析,但是想找个对象去接收,不要使用org.json.JSONObject, 如果使用org.json.JSONObject;在解析的过程中会被忽略掉,不会得到对应的结果。 如果你使用的是fastjson可以使用com.alibaba.fastjson.JSONObject 可以得到想要的结果但是不推荐(FastJson已确认可以) 同理Gson等也要使用对应包下的JSONObject才可以(Gson未确认,处于猜想阶段)
- 如果json解析过程中出错,fastjson和gson都会立即中断解析,后面字段将不会解析 但是jackjson会跳过出错字段继续解析,最终结果只会缺少出错的字段
- JavaBean set 和 get 方法都要设置为public
Kotlin
//”{“name”:”lihang”,”desc”:”dashuaibi”}”
1
2
3
4
5
6
7
8
9
data class GsonBean(val name: String, val desc: String) {
}
val gsonString = "{\"desc\":\"dashuaibi\"}"
// 结论:name 字段为null
//使用 deployDefaultValue name : null
val gString = "{\"name\":null,\"desc\":\"dashuaibi\"}"
//使用 deployDefaultValue name : ""
1
2
3
4
5
val gsonString = "{\"desc\":\"dashuaibi\"}"
data class GsonBean(val name: String = "lihang", val desc: String) {
}
// name : null
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class GsonBean {
var name: String = "lihang"
val desc: String = ""
}
val gsonString = "{\"desc\":\"dashuaibi\"}"
// name = lihang
// desc = dashuaibi
val gString = "{\"name\":null,\"desc\":\"dashuaibi\"}"
// name = null
// desc = dashuaibi
//使用 deployDefaultValue name : ""
结论:
- 构造方法默认值是没有作用的
- 在拥有无参构造函数的情况下,成员方法默认值是有作用的,在Json没有该变量的时候会采用默认变量
- deployDefaultValue只会在Json中为null的时候起作用,如果没有该变量是没有作用的
问题:为什么Gson可以创建(没有无参构造方法的类)的对象
Gson创建(没有无参构造方法的类)的对象的代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public static UnsafeAllocator create() {
// 最关键
try {
// 反射找到sun.misc.Unsafe类
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
// 找到sun.misc.Unsafe类中的theUnsafe属性
Field f = unsafeClass.getDeclaredField("theUnsafe");
// 激活theUnsafe属性
f.setAccessible(true);
// 得到theUnsafe的对象
final Object unsafe = f.get(null);
// 反射allocateInstance方法
final Method allocateInstance = unsafeClass.getMethod("allocateInstance", Class.class);
return new UnsafeAllocator() {
@Override
@SuppressWarnings("unchecked")
public <T> T newInstance(Class<T> c) throws Exception {
assertInstantiable(c);
// 调用allocateInstance方法,创建类型为c的对象
return (T) allocateInstance.invoke(unsafe, c);
}
};
} catch (Exception ignored) {
}
// 第二步的实现方案和第一步其实一样,所以忽略
...
// 第三步,在我的版本源码中ObjectInputStream找不到newInstance方法,所以忽略
...
}
sun.misc.Unsafe,可以无视对象的构造方法,创建新的对象 sun.misc.Unsafesh收集了很多底层的不安全的操作方法。尽管类和方法是开放的,但是要谨慎的使用它,因为只有信任的代码才可以使用它。 allocateInstance方法:创建一个实例,但是不运行它的构造方法,请手动初始化。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
data class PigStoreResponse(
val code: Int,
var `data`: String,
val msg: String
){
init {
print("init")
}
}
var json = "{\"code\":1}"
var data = Gson().fromJson(json, PigStoreResponse::class.java)
if (data.data != null) {
println("if")
} else {
println("else")
}
// println结果:
// else
结论:
- 在《if (data.data != null) 》处没有报错,代表即使声明为非空变量,在做null判断的时候也不会报错;
- 没有执行《print(“init”)》表示,Gson对于(没有无参构造方法的类) 是不执行构造方法的
fastJson
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"data": [
{
"refId": "EIJHOVJL732BNIFEF",
"type": "cube",
"version": "14",
},
{
"refId": "EIJHOVJL732BNIFEF",
"type": "cube",
"version": "14",
}
]
}
如果使用 fastJson 解析上面的 json 字符串
1
2
3
4
5
6
7
8
9
obj.getJSONArray("data")// 可以正常获取数据,多次调用 obj.getJSONArray("data") 获取到的是同一个对象。
obj.getString("data");// 可以获取一个 Json 字符串
obj.getIntValue("data") // 会抛出异常 com.alibaba.fastjson.JSONException
obj.getJSONObject("data") // 会抛出异常 com.alibaba.fastjson.JSONException
obj.getInvalue("ddddd") // 如果使用一个不存在的 key 获取到的是 0
obj.getInteger("ddddd")// 获取到的是 null,如果key不存在,get 任何对象类型的数据获取到的都是 null
obj.getJSONArray("data").getJSONObject(0)// 能正常获取数据
obj.getJSONArray("data").getJSONArray(0)// Method threw 'java.lang.ClassCastException' exception. com.alibaba.fastjson.JSONObject cannot be cast to com.alibaba.fastjson.JSONArray
org.json.JSONObject
待补充
fastJson Gson 在使用时的区别
使用 fastJson 在 toJson 的时候,遍历的是对象以get开头的方法 和 public 属性的成员便来给你 使用 Gson 在 toJson 的时候,遍历的是对象的成员变量