无法将空值放入JSON对象中。

48

我正在尝试使用JSON传递参数给API。

class Sample
{ ...
   String token;
...

void method()
{ ...
    JSONObject params = new JSONObject();
    params.put(KEY_TOKEN,token);
    params.put(KEY_DATE,date);

    Log.e("params ",params+"");


      ...  }    

我获取到params的值为{"date":"2017-06-19"},但是没有看到token。 我没有初始化token,它的值为空,因为它是一个实例变量。所以未初始化的值是否不包括在内呢?


你可以检查一下,对吧?token=null - user7294900
只需要询问未初始化的值。 - Aishwarya
@aish:由于tokenString类型的实例成员,它的默认值为null,所以结果相同。 - T.J. Crowder
6个回答

99

文档的第一段中,有这样一句话:

Values may not be null, NaNs, infinities, or of any type not listed here.

所以是的,它确实是“...某些值不包括null值...”(编辑:这是您原始问题中的引用;您更新后的问题将其更改为“未初始化的值”,但对象引用的默认值为null,所以...)

这是该类的“特性”;JSON本身可以很好地理解null。在文档的后面部分,它说您可以使用“sentinal value”NULL来表示null。这似乎有点奇怪。关于这个还有一个注意事项:

警告:这个类用两种不兼容的方式表示null:标准Java null引用和哨兵值NULL。特别是,调用put(name, null)会从对象中删除具有指定名称的条目,但是put(name, JSONObject.NULL)会存储其值为JSONObject.NULL的条目。

所以:

params.put(KEY_TOKEN, token == null ? JSONObject.NULL : token);

但是该字符串对象的值为空,因此它应该理解它。如果不是,则必须抛出错误。 - Aishwarya
3
@aish:和 JSONObject 的设计者交流一下。他们是决定让它以这种方式运作的人。好消息是,确实有一种方法可以将 null 放入其中,只是你必须用非标准的方式来实现。这似乎有点傻,但我不知道他们所面临的所有设计限制。 - T.J. Crowder
由于空值被理解为未设置和不必要的,因此在JSON中,任何有价值的空值都会被删除。因此,在网络传输期间,它从JSON字符串中删除,减少了负载。 - BhalchandraSW
3
应该是一次“删除(remove)”操作,而不是“放置(put)”操作。不以正常、合理的方式处理“null”值是很奇怪的。 :-) - T.J. Crowder
谢谢,有了这个解决方案,我仍然可以通过网络获取密钥,Java的null会(就像你所说的)删除密钥。 - Joaquim Ley
2
而且 jsonObject.optString(key) 返回的字符串是 "null" 而不是实际的 null。这是我见过的最糟糕的 JSON 实现。 - soger

14
根据RFC 4627,JSON将 null 符号视为有效值。 问题在于,JSON中的 null 是Javascript中的 null 值。相比之下,Java版本的 null(根据专家)更接近于Javascript的 undefined 值。 org.json 库的原作者决定,JSONObject 应以与Javascript语义一致的方式处理JSON null。因此,它被表示为Java中的 JSONObject.NULL……并且不等于 null

4

我通过创建一个继承JSONObject类的类,并重载put方法,在传递的对象为null时使用JSONObject.NULL来解决这个问题。

public class ObjectJSON extends JSONObject {
    public JSONObject put(String key, Object value) throws JSONException {
        return super.put(key, value == null ? JSONObject.NULL : value);
    }
}

1
无法直接使用该解决方案,因为无法从net.sf.json.JSONObject扩展JSONObject类,因为该类是final的。我所做的是创建一个实用方法,即public static Object getJSONObjectValue(Object value){return value == null?"null":value;},然后在调用JSONObject类的put方法时调用此方法,如下所示... jsonObject.put(“key”,Utility.getJSONObjectValue(objectValue)); - Winter MC

4
我通过使用字符串表示来创建空的JSON值,并将其插入对象中来解决了这个问题。显然这是一个hack,但它可以运行。
JSONObject obj = new JSONObject("{\"keyword\": null}");
System.out.println(obj); // {"keyword": null}

1
Json本身可以接受null,但JSONOBJECT类不行。因此,您无法这样做。尝试使用jackson/gson进行json和对象映射。如果需要帮助,请告诉我。

1
我修复了这个“特性”,并创建了这个项目https://github.com/leonardofel/JSON-java-put-null-fix
使下面的代码成为可能:
JSONObject j = new JSONObject().put("myPreciousNull", null);
System.out.println(j.toString());

打印:

{"myPreciousNull":null}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接