我正在开发一个使用JSON进行服务器通信的Android应用程序,当我尝试解析我的json文件时,我遇到了一个奇怪的问题。
这是我服务器的json
{
"street2": null,
"province": null,
"street1": null,
"postalCode": null,
"country": null,
"city": null
}
我通过在我的地址Json-object上调用String city = address.optString("city", "")
来获取City的值。对于这种情况,我期望city
为空(这就是optString的用途不是吗?)但事实上它包含字符串“null”。因此,当String包含文本时,进一步的null-或isEmpty-checks将返回false。如果我调用address.isNull("city")
,则返回true,这是正确的。只有optString
失败。
我无法在Google或Stackoverflow上找到此问题。我真的不明白它是如何发生的,因为我认为optString
会完全符合我的预期。谁知道这里出了什么问题?
答案 0 :(得分:83)
你并不是唯一一个遇到这个问题并且摸不着头脑的人,在思考"他们真的有这个意思吗?"根据AOSP问题,Google工程师 认为这是一个错误,但他们必须与org.json实现兼容,甚至错误兼容。
如果您考虑一下,这是有道理的,因为如果在其他Java环境中使用相同库的相同代码在Android中表现不同,则在使用第三方库时会出现主要的兼容性问题。即使意图是好的并且它确实修复了错误,它也会开辟出一整套新的蠕虫。
根据AOSP issue:
这种行为是有意的;我们竭尽全力与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);
}
答案 1 :(得分:23)
你基本上有两个选择:
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"
}
答案 2 :(得分:1)
通过简单地将"null"
替换为""
,摆脱了这种情况。
String city = address.optString("city").replace("null", "");
答案 3 :(得分: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");
你得到的是String" 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;
}
答案 4 :(得分:0)
如果key的值为null,则如下所示
{
"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并赋值为零,否则它将从key获得实际值。
答案 5 :(得分:0)
以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 for fallback参数。
答案 6 :(得分: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);
}
}
}
答案 7 :(得分: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;
}
}
答案 8 :(得分:0)
我喜欢这样...
on(trampolineExecutionContext)