web-dev-qa-db-fra.com

JSON jsonObject.optString () renvoie String "null"

Je développe une application Android qui utilise JSON pour la communication serveur et j'ai un problème étrange lorsque j'essaie d'analyser mon fichier JSON.

Ceci est mon JSON du serveur

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

J'obtiens la valeur pour City en appelant String city = address.optString("city", "") sur mon adresse Json-object. Pour cette situation, je m'attends à ce que city soit vide (c'est ce que optString est ici pour n'est-ce pas?) Mais en fait, il contient la chaîne "null". Ainsi, des vérifications NULL ou ISEmpty supplémentaires renverront false car String contient du texte. Si j'appelle address.isNull("city"), il retourne true, ce qui est correct. Seul optString échoue.

Je n'ai rien trouvé sur Google ou Stackoverflow pour résoudre ce problème. Je ne comprends pas vraiment comment cela peut arriver car je pensais que optString ferait exactement ce à quoi je m'attendais. Quelqu'un sait ce qui ne va pas ici?

49
joschplusa

Vous n'êtes pas seul à courir dans ce problème et à vous gratter la tête, en pensant "Est-ce qu'ils auraient vraiment voulu dire cela?" Selon un problème d'AOSP, les ingénieurs de Google ont faitconsidérez cela comme un bogue, mais ils devaient être compatibles avec l'implémentation org.json, même avec un bogue. 

Si vous y réfléchissez, c'est logique, car si le même code utilisant les mêmes bibliothèques s'exécutant dans d'autres environnements Java se comporte différemment sous Android, des problèmes de compatibilité majeurs se poseraient si vous utilisiez des bibliothèques tierces. Même si les intentions étaient bonnes et que cela corrigeait vraiment les bugs, cela ouvrirait une nouvelle boîte de Pandore.

Selon le numéro de l'AOSP :

Le comportement est intentionnel; nous avons fait tout notre possible pour être compatibles avec les bogues avec org.json. Maintenant que cela est corrigé, il est difficile de savoir si nous devons également corriger notre code. Les applications peuvent s’en remettre à ce comportement bogué.

Si cela vous cause du chagrin, je vous recommande de contourner le problème en utilisant un mécanisme différent pour tester null, tel que json.isNull ().

Voici une méthode simple pour vous aider:

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

Vous avez essentiellement 2 choix:

1) Envoyer une charge JSON avec des valeurs null

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

Vous devrez vérifier les valeurs NULL et les analyser en conséquence:

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

2) N'envoyez pas les clés avec des valeurs null et utilisez directement optString (key, null) (vous devriez économiser de la bande passante).

{
"street2": "s2",
"province": "p1"
}
23
dev.serghini
if (json != null && json.getString(KEY_SUCCESS) != null){
     // PARSE RESULT 
}else{
    // SHOW NOTIFICIATION: URL/SERVER NOT REACHABLE

}

c'est pour vérifier json null avec la clé Word.

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

ce que vous obtenez est String "null" et non null.

ton utilisation

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

première vérification avec isNull () .... si vous ne pouvez pas travailler, essayez belows

et aussi vous avez JSONObject.NULL pour vérifier la valeur null ...

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

et dans votre cas aussi vérifier 

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

Si vous devez analyser json en premier et manipuler l’objet plus tard, laissez ceci essayer.

Analyseur

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

Gestionnaire

 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;                 
  }
0
bhanu Prakash Dave

On s'est débarrassé de cette situation en remplaçant simplement "null" par "".

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

Mon analyseur Josn a été long et a dû créer une nouvelle classe pour résoudre ce problème. Il suffit ensuite d'ajouter une ligne supplémentaire dans chaque méthode et de renommer le nom de la propriété JSONObject actuelle. . 

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

Voici ma classe avec les méthodes dont j'avais besoin, vous pouvez ajouter plus

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

}

0
Galeen

Si les valeurs de la clé sont nulles, comme ci-dessous 

{

  "status": 200,

  "message": "",

  "data": {

    "totalFare": null,
  },

}

check with "isNull" , for Eg:

String strTotalFare;

if (objResponse.isNull("totalFare")) 

{

  strTotalFare = "0";

} else {

 strTotalFare = objResponse.getString("totalFare");

}

si la valeur est "null" pour la clé "totalFare", la fonction ci-dessus entrera dans si et assignera la valeur zéro sinon elle obtiendra la valeur réelle de la clé.

0
Digvijay Machale

Sur la base de la réponse de Matt Quigley, voici le code si vous souhaitez imiter toutes les fonctionnalités d’optString, y compris la partie de secours, écrite en Kotlin et 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;
 }

Passez simplement null pour le paramètre fallback si vous n'avez pas besoin du repli.

0
Bret Smith