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的值“我是值”。

popo_2020-10-23
18-47-33.jpg

那如果Json的内容是这样的,k不存在了呢?

{
    "t" : "我是值"
}

再次运行代码会抛出JSONException

popo_2020-10-23
18-50-24.jpg

使用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();
}

然后成功的返回了我期望的空字符串返回值。

截屏2020-10-23
下午7.51.58.png

直到有一天Json数据变成了这种的,k还存在,只是变成了null。

{
    "k" : null
}

然后解析出来的k是"null",这就很尴尬了,就算这个k是null,我也希望它解析成空字符串。

截屏2020-10-23
下午7.54.30.png

判断是否为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();
}

最后结果也如我所愿,成功的输出了空字符串

截屏2020-10-23
下午7.56.25.png

为什么会输出”null”

现在我知道在解析字符串的时候应该先判断这个值是否为null然后在使用optString获取值,那为什么值为null的时候会出现"null"呢?
点开optString(@Nullable String name)会发现它调用了optString(@Nullable String name, @NonNull String fallback),然后查看该函数可以看到,当name对应到值存在的时候就直接返回,否则返回fallback的值。而optString(@Nullable String name)默认使用的是空字符作为fallback。 截屏2020-10-23
下午7.21.42.png

通过添加断点,可以看到object的值已经变成了"null"截屏2020-10-23
下午7.27.27.png

opt(@Nullable String name)仅仅是将nameValuePairs对应的值取出来,所以重点变成了nameValuePairs是怎赋值进去的。

截屏2020-10-23
下午7.28.26.png

当我们使用Json字符串创建JSONObject对象的时候,会通过JSONTokener对字符串进行解析,如下:

截屏2020-10-23
下午7.34.41.png

当值为null的时候会执行到default语句,调用readLiteral()

截屏2020-10-23
下午7.37.22.png

当值为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",那一切至此就可以结案了。

截屏2020-10-23
下午7.43.35.png

总结

在使用JSONObject解析字符串的时候,如果需求是在值不存在或者为null的时候返回空字符串,可以先对该值进行isNull判断,如果不为null就使用optString获取值,否则返回空字符串。同样的对于其他的optXXXX方法使用前也需要注意一下,比如optJSONObject,该方法可以解析一个JSONObject对象,如果不存在就返回null,不过在使用这个返回的对象之前还是要先进行非空判断的。

Search by:GoogleBingBaidu