简体   繁体   English

JSON jsonObject.optString() 返回字符串“null”

[英]JSON jsonObject.optString() returns String “null”

I'm developing an Android App which uses JSON for the server communication and I've got a weird problem when I'm trying to parse my json file.我正在开发一个使用 JSON 进行服务器通信的 Android 应用程序,当我尝试解析我的 json 文件时遇到了一个奇怪的问题。

This is my json from the server这是我来自服务器的 json

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

I'm getting the value for City by calling String city = address.optString("city", "") on my address Json-object.我通过在我的地址 Json 对象上调用String city = address.optString("city", "")来获取 City 的值。 For this situation I'm expecting city to be empty (that's what optString is here for isn't it?) but in fact it contains the String "null".对于这种情况,我希望city为空(这就是 optString 的用途,不是吗?)但实际上它包含字符串“null”。 So further null- or isEmpty-checks will return false as the String contains text.因此,进一步的 null 或 isEmpty 检查将返回 false,因为 String 包含文本。 If I call address.isNull("city") it returns true which is correct.如果我调用address.isNull("city")它返回 true,这是正确的。 Only optString fails.只有optString失败。

I couldn't find anything on Google or Stackoverflow for this problem.我在 Google 或 Stackoverflow 上找不到有关此问题的任何信息。 I don't really understand how it can happen as I thought optString would do exactly what I expected.我真的不明白它是如何发生的,因为我认为optString会完全符合我的预期。 Anybody knows what's going wrong here?有人知道这里出了什么问题吗?

You're not alone in running into this problem and scratching your head, thinking "Could they really have meant this?"你不是唯一一个遇到这个问题并挠头的人,想“他们真的是这个意思吗?” According to an AOSP issue, the Google engineers did consider this a bug , but they had to be compatible with the org.json implementation, even bug-compatible.根据 AOSP 问题,Google 工程师确实认为这是一个错误,但他们必须与 org.json 实现兼容,甚至与错误兼容。

If you think about it, it makes sense, because if the same code which uses the same libraries run in other Java environments behaves differently in Android, there would be major compatibility problems when using 3rd party libraries.如果你仔细想想,这是有道理的,因为如果在其他 Java 环境中运行的相同代码在 Android 中的行为不同,那么在使用 3rd 方库时就会出现重大的兼容性问题。 Even if the intentions were good and it truly fixed bugs, it would open up a whole new can of worms.即使意图是好的并且它确实修复了错误,它也会打开一个全新的蠕虫罐。

According to the AOSP issue :根据AOSP 问题

The behavior is intentional;该行为是故意的; we went out of our way to be bug-compatible with org.json.我们竭尽全力与 org.json 进行错误兼容。 Now that that's fixed, it's unclear whether we should fix our code as well.现在已经解决了,不清楚我们是否也应该修复我们的代码。 Applications may have come to rely on this buggy behavior.应用程序可能已经开始依赖这种有问题的行为。

If this is causing you grief, I recommend you workaround by using a different mechanism to test for null, such as json.isNull().如果这让您感到悲伤,我建议您使用不同的机制来测试 null,例如 json.isNull()。

Here's a simple method to help you out:这里有一个简单的方法可以帮助您:

/** 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);
}

You basically have 2 choices:你基本上有两个选择:

1) Send a JSON payload with null values 1) 发送一个空值的 JSON 负载

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

You will have to check for null values and parse them accordingly:您必须检查空值并相应地解析它们:

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

2) Do not send the keys with null values and use optString(key, null) directly (should save you bandwidth). 2)不要发送带有空值的键,直接使用 optString(key, null) (应该可以节省带宽)。

{
"street2": "s2",
"province": "p1"
}

得到了通过简单地更换驱除掉这种情况下"null"""

String city = address.optString("city").replace("null", "");

Using Matt Quigley's answer as a basis, here is the code if you desire to mimic the full functionality of optString, including the fallback portion, written in Kotlin and Java.使用 Matt Quigley 的答案作为基础,如果您想模拟 optString 的全部功能,包括使用 Kotlin 和 Java 编写的回退部分,这里是代码。

Kotlin:科特林:

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

Java:爪哇:

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

Simply pass in null for the fallback parameter if you don't need the fallback.如果您不需要回退,只需为回退参数传入 null。

if (json != null && json.getString(KEY_SUCCESS) != null){
     // PARSE RESULT 
}else{
    // SHOW NOTIFICIATION: URL/SERVER NOT REACHABLE

} }

that is for checking json null with there key word.那是用于检查带有关键字的 json null 。

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

this you get is String "null" not null.你得到的是字符串“空”而不是空。

your shoud use你应该使用

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

first check with isNull()....if cant work then try belows首先检查 isNull()....如果不能工作然后尝试下面

and also you have JSONObject.NULL to check null value...而且你还有 JSONObject.NULL 来检查空值......

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

and in your case also check在你的情况下也检查

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

If you must parse json first and handle object later, let try this如果你必须先解析json然后处理对象,让我们试试这个

Parser解析器

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

Handler处理程序

 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;                 
  }

If values for key is null like below如果键的值为空,如下所示

{

  "status": 200,

  "message": "",

  "data": {

    "totalFare": null,
  },

}

check with "isNull" , for Eg:

String strTotalFare;

if (objResponse.isNull("totalFare")) 

{

  strTotalFare = "0";

} else {

 strTotalFare = objResponse.getString("totalFare");

}

if value is "null" for key "totalFare", above function will enter in if and assign value zero else it will get actual value from key.如果键“totalFare”的值为“null”,则上述函数将输入 if 并赋值为零,否则它将从键中获取实际值。

My Josn parser was long and had to create a new class to fix that, then just had to add 1 extra line in each method and rename current JSONObject property name, so all other calls were referencing to my new class instead to JSONObject.我的 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;
}

Here is my class with the methods I needed, you can add more这是我的课程,其中包含我需要的方法,您可以添加更多

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);
    }
}

} }

I ended up creating a utility class for this purpose:我最终为此创建了一个实用程序类:

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;
    }
}

I do like this...我喜欢这个...

String value; 

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

      

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM