73

我正在开发一个使用 JSON 进行服务器通信的 Android 应用程序,当我尝试解析我的 json 文件时遇到了一个奇怪的问题。

这是我来自服务器的 json

{
    "street2": null,
    "province": null,
    "street1": null,
    "postalCode": null,
    "country": null,
    "city": null
}

我通过调用String city = address.optString("city", "")我的地址 Json 对象来获得 City 的价值。对于这种情况,我希望city为空(这就是 optString 的用途,不是吗?)但实际上它包含字符串“null”。因此,进一步的 null 或 isEmpty 检查将返回 false,因为 String 包含文本。如果我调用address.isNull("city")它返回 true ,这是正确的。只会optString失败。

对于这个问题,我在 Google 或 Stackoverflow 上找不到任何东西。我真的不明白它是如何发生的,因为我认为它optString会完全符合我的预期。有人知道这里出了什么问题吗?

4

9 回答 9

114

遇到这个问题并挠头,想“他们真的是这个意思吗?”的不止你一个人。根据 AOSP 问题,Google 工程师确实 认为这是一个错误,但他们必须与 org.json 实现兼容,甚至是与错误兼容。

如果您考虑一下,这是有道理的,因为如果在其他 Java 环境中运行的使用相同库的相同代码在 Android 中的行为不同,那么在使用 3rd 方库时会出现严重的兼容性问题。即使意图是好的并且它确实修复了错误,它也会打开一个全新的蠕虫罐头。

根据AOSP 问题

行为是故意的;我们竭尽全力与 org.json 兼容。既然已经解决了,我们是否也应该修复我们的代码还不清楚。应用程序可能已经开始依赖这种错误的行为。

如果这让您感到悲伤,我建议您使用不同的机制来测试 null,例如 json.isNull()。

这里有一个简单的方法可以帮助你:

/** Return the value mapped by the given key, or {@code null} if not present or null. */
public static String optString(JSONObject json, String key)
{
    // http://code.google.com/p/android/issues/detail?id=13830
    if (json.isNull(key))
        return null;
    else
        return json.optString(key, null);
}
于 2014-04-30T01:04:43.393 回答
25

你基本上有2个选择:

1) 发送带有空值的 JSON 有效负载

{
"street2": "s2",
"province": "p1",
"street1": null,
"postalCode": null,
"country": null,
"city": null
}

您将必须检查空值并相应地解析它们:

private String optString_1(final JSONObject json, final String key) {
    return json.isNull(key) ? null : json.optString(key);
}

2)不要发送带有空值的键并直接使用 optString(key, null) (应该可以节省带宽)。

{
"street2": "s2",
"province": "p1"
}
于 2013-08-14T22:09:55.483 回答
2

"null"只需用替换即可摆脱这种情况""

String city = address.optString("city").replace("null", "");
于 2018-11-30T11:35:26.713 回答
1

使用 Matt Quigley 的回答作为基础,如果您希望模仿 optString 的全部功能,包括后备部分,这里是代码,用 Kotlin 和 Java 编写。

科特林:

fun optString(json: JSONObject, key: String, fallback: String?): String? {
    var stringToReturn = fallback
    if (!json.isNull(key)) {
        stringToReturn = json.optString(key, null)
    }
    return stringToReturn
}

爪哇:

public static String optString(JSONObject json, String key, String fallback) {
    String stringToReturn = fallback;
    if (!json.isNull(key)) {
        stringToReturn = json.optString(key, null);
    }
    return stringToReturn;
 }

如果不需要回退,只需为回退参数传入 null。

于 2017-07-05T23:15:21.487 回答
0

我喜欢这样...

String value; 

 if(jsonObject.get("name").toString().equals("null")) {
  value = ""; 
 }else {
  value = jsonObject.getString("name"); 
 }

      
于 2020-09-13T04:32:35.893 回答
0

我的 Josn 解析器很长,必须创建一个新类来解决这个问题,然后只需在每个方法中添加 1 行并重命名当前 JSONObject 属性名称,因此所有其他调用都引用我的新类而不是 JSONObject。

    public static ArrayList<PieceOfNews> readNews(String json) {
    if (json != null) {
        ArrayList<PieceOfNews> res = new ArrayList<>();
        try {
            JSONArray jsonArray = new JSONArray(json);
            for (int i = 0; i < jsonArray.length(); i++) {
                //before JSONObject jo = jsonArray.getJSONObject(i);
                JSONObject joClassic = jsonArray.getJSONObject(i);
                //facade
                FixJsonObject jo = new FixJsonObject(joClassic);
                PieceOfNews pn = new PieceOfNews();
                pn.setId(jo.getInt("id"));
                pn.setImageUrl(jo.getString("imageURL"));
                pn.setText(jo.getString("text"));
                pn.setTitle(jo.getString("title"));
                pn.setDate(jo.getLong("mills"));
                res.add(pn);
            }
            return res;
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    return null;
}

这是我的课程,其中包含我需要的方法,您可以添加更多

public class FixJsonObject {
private JSONObject jsonObject;

public FixJsonObject(JSONObject jsonObject) {
    this.jsonObject = jsonObject;
}

public String optString(String key, String defaultValue) {
    if (jsonObject.isNull(key)) {
        return null;
    } else {
        return jsonObject.optString(key, defaultValue);
    }
}

public String optString(String key) {
    return optString(key, null);
}

public int optInt(String key) {
    if (jsonObject.isNull(key)) {
        return 0;
    } else {
        return jsonObject.optInt(key, 0);
    }
}

public double optDouble(String key) {
    return optDouble(key, 0);
}

public double optDouble(String key, double defaultValue) {
    if (jsonObject.isNull(key)) {
        return 0;
    } else {
        return jsonObject.optDouble(key, defaultValue);
    }
}

public boolean optBoolean(String key, boolean defaultValue) {
    if (jsonObject.isNull(key)) {
        return false;
    } else {
        return jsonObject.optBoolean(key, defaultValue);
    }
}

public long optLong(String key) {
    if (jsonObject.isNull(key)) {
        return 0;
    } else {
        return jsonObject.optLong(key, 0);
    }
}

public long getLong(String key) {
    return optLong(key);
}

public String getString(String key) {
    return optString(key);
}

public int getInt(String key) {
    return optInt(key);
}

public double getDouble(String key) {
    return optDouble(key);
}

public JSONArray getJSONArray(String key) {
    if (jsonObject.isNull(key)) {
        return null;
    } else {
        return jsonObject.optJSONArray(key);
    }
}

}

于 2018-06-05T10:01:17.567 回答
0

我最终为此目的创建了一个实用程序类:

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.json.JSONException;
import org.json.JSONObject;

final public class JsonUtil {
    
    @Nullable
    public static String optString(
            @NonNull JSONObject object,
            @NonNull String key
    ) throws JSONException {
        if (object.has(key) && !object.isNull(key)) {
            return object.getString(key);
        }
        
        return null;
    }
}
于 2020-09-09T17:54:46.730 回答
0

如果键的值为空,如下所示

{

  "status": 200,

  "message": "",

  "data": {

    "totalFare": null,
  },

}

check with "isNull" , for Eg:

String strTotalFare;

if (objResponse.isNull("totalFare")) 

{

  strTotalFare = "0";

} else {

 strTotalFare = objResponse.getString("totalFare");

}

如果键“totalFare”的值为“null”,则上述函数将输入 if 并将值分配为零,否则它将从键中获取实际值。

于 2017-06-12T06:11:34.423 回答
0
if (json != null && json.getString(KEY_SUCCESS) != null){
     // PARSE RESULT 
}else{
    // SHOW NOTIFICIATION: URL/SERVER NOT REACHABLE

}

那是用那里的关键字检查json null。

JSONObject json = new JSONObject("{\"hello\":null}");
json.getString("hello");

你得到的是字符串“null”而不是null。

你应该使用

if(json.isNull("hello")) {
    helloStr = null;
} else {
    helloStr = json.getString("hello");
}

首先检查 isNull()....如果不能工作,那么试试下面

而且你有 JSONObject.NULL 来检查空值......

 if ((resultObject.has("username")
    && null != resultObject.getString("username")
    && resultObject.getString("username").trim().length() != 0)
    {
           //not null
    }

在你的情况下还要检查

resultObject.getString("username").trim().eqauls("null")

如果您必须先解析 json 并稍后处理对象,请试试这个

解析器

Object data = json.get("username");

处理程序

 if (data instanceof Integer || data instanceof Double || data instanceof Long) {
        // handle number ;
  } else if (data instanceof String) {
        // hanle string;               
  } else if (data == JSONObject.NULL) {
        // hanle null;                 
  }
于 2015-08-28T10:12:23.380 回答