getString还是optString?
使用Java的JSONObject解析Json数据时经常会遇到需要解析字符串的情况,那是该使用
getString
还是optString
或者其他呢?
Json
假设现在有这样一个Json字符串,现在要获取k
的值,要怎么做呢?
{
"k" : "我是值"
}
使用getString
我心中暗暗自喜,这还不简单,直接使用JSONObject解析不就行了,看我操作一波。
String json = "{\"k\":\"我是值\"}";
try {
JSONObject jsonObject = new JSONObject(json);
String k = jsonObject.getString("k");
System.out.println("k:" + k);
} catch (JSONException e) {
e.printStackTrace();
}
成功获取到了k的值“我是值”。
那如果Json的内容是这样的,k不存在了呢?
{
"t" : "我是值"
}
再次运行代码会抛出JSONException
使用optString
虽然异常被catch住了,但是代码也被中断了,大多数情况我希望他能在值不存在的时候返回一个空字符串。于是我又改了一下代码,把getString
换成了optString
(为了演示的清晰,我把空字符串使用中文输出了出来)。
String json = "{\"t\":\"我是值\"}";
try {
JSONObject jsonObject = new JSONObject(json);
String k = jsonObject.optString("k");
System.out.println("k:" + (k.isEmpty() ? "空字符串" : k));
} catch (JSONException e) {
e.printStackTrace();
}
然后成功的返回了我期望的空字符串返回值。
直到有一天Json数据变成了这种的,k还存在,只是变成了null。
{
"k" : null
}
然后解析出来的k是"null"
,这就很尴尬了,就算这个k是null,我也希望它解析成空字符串。
判断是否为null
当然这难不倒我,经过观察我发现,只有当这个数据是null的时候才会出现这个情况,那我提前判断一下是否为null然后在取值不就行了吗,于是有了下面的代码。
String json = "{\"k\": null }";
try {
JSONObject jsonObject = new JSONObject(json);
String k = "";
if (!jsonObject.isNull("k")) {
k = jsonObject.optString("k");
}
System.out.println("k:" + (k.isEmpty() ? "空字符串" : k));
} catch (JSONException e) {
e.printStackTrace();
}
最后结果也如我所愿,成功的输出了空字符串
为什么会输出”null”
现在我知道在解析字符串的时候应该先判断这个值是否为null然后在使用optString获取值,那为什么值为null的时候会出现"null"
呢?
点开optString(@Nullable String name)
会发现它调用了optString(@Nullable String name, @NonNull String fallback)
,然后查看该函数可以看到,当name对应到值存在的时候就直接返回,否则返回fallback的值。而optString(@Nullable String name)
默认使用的是空字符作为fallback。
通过添加断点,可以看到object的值已经变成了"null"
。
而opt(@Nullable String name)
仅仅是将nameValuePairs对应的值取出来,所以重点变成了nameValuePairs是怎赋值进去的。
当我们使用Json字符串创建JSONObject对象的时候,会通过JSONTokener
对字符串进行解析,如下:
当值为null的时候会执行到default语句,调用readLiteral()
。
当值为null的时候会返回一个JSONObject.NULL
对象,而这个对象的toString方法刚好就是"null"
。
![截屏2020-10-23
下午7.39.59.png](http://pfp.ps.netease.com/kmspvt/file/5f92c1442dcade27240ad9e81LDXu6U801?sign=1kTjrSlMRfw-
GxkX_cfirGgpR6k=&expire=1603957453)
在optString
方法里面会获取对象的toString
值,所以最终返回了"null"
,那一切至此就可以结案了。
总结
在使用JSONObject
解析字符串的时候,如果需求是在值不存在或者为null的时候返回空字符串,可以先对该值进行isNull
判断,如果不为null就使用optString
获取值,否则返回空字符串。同样的对于其他的optXXXX
方法使用前也需要注意一下,比如optJSONObject
,该方法可以解析一个JSONObject对象,如果不存在就返回null,不过在使用这个返回的对象之前还是要先进行非空判断的。