我在JSONObject.toString(int)文档中注意到了这一点
抛出:JSONException - 如果对象包含无效的数字。
如果事先完成NaN / Infinity检查(在解析时和.put("blah", Double.NAN)
之类的语句中,对象如何包含无效数字?
哪个陈述会抛出该异常?
我还在文档中读到.toString()没有args不会抛出任何东西,所以我认为异常可能与作为参数传递的整数有关;但即使有零,负或Integer.MAX / MIN_VALUE,它仍然有效。
所以当人们期望.toString(int)抛出异常时应该如何处理它?</ p>
答案 0 :(得分:2)
toString()
方法不会抛出异常,因为它必须覆盖public void toString()
java.lang.Object
方法的签名。在org.json.JSONObject
泛型toString()
方法实际上无声地失败,因为源代码是:
/**
* Make a JSON text of this JSONObject. For compactness, no whitespace is
* added. If this would not result in a syntactically correct JSON text,
* then null will be returned instead.
* <p>
* Warning: This method assumes that the data structure is acyclical.
*
* @return a printable, displayable, portable, transmittable representation
* of the object, beginning with <code>{</code> <small>(left
* brace)</small> and ending with <code>}</code> <small>(right
* brace)</small>.
*/
public String toString() {
try {
return this.toString(0);
} catch (Exception e) {
return null;
}
}
此方法依赖于toString(int)
方法,如果它抛出异常,它会捕获它并返回null。
根据toString(int)
描述,当org.json.JSONObject
在其中一个元素中包含无效数字时,抛出异常;但是查看代码可能会因为其他原因而抛出此异常。
当您使用toString(int)
时,堆栈跟踪最终调用write()
方法来解析对象本身,对于从json对象到字符串的一些转换,可能抛出异常:
static final Writer writeValue(Writer writer, Object value,
int indentFactor, int indent) throws JSONException, IOException {
if (value == null || value.equals(null)) {
writer.write("null");
} else if (value instanceof JSONObject) {
((JSONObject) value).write(writer, indentFactor, indent);
} else if (value instanceof JSONArray) {
((JSONArray) value).write(writer, indentFactor, indent);
} else if (value instanceof Map) {
new JSONObject((Map<String, Object>) value).write(writer, indentFactor, indent);
} else if (value instanceof Collection) {
new JSONArray((Collection<Object>) value).write(writer, indentFactor,
indent);
} else if (value.getClass().isArray()) {
new JSONArray(value).write(writer, indentFactor, indent);
} else if (value instanceof Number) {
writer.write(numberToString((Number) value));
} else if (value instanceof Boolean) {
writer.write(value.toString());
} else if (value instanceof JSONString) {
Object o;
try {
o = ((JSONString) value).toJSONString();
} catch (Exception e) {
throw new JSONException(e);
}
writer.write(o != null ? o.toString() : quote(value.toString()));
} else {
quote(value.toString(), writer);
}
return writer;
}
但是,正如您在问题中所说(以及@Carlos Rodriguez评论)所有检查都是在创建对象时执行的,可能toString(int)
方法永远不会抛出异常。
希望它有所帮助,
答案 1 :(得分:1)
有助于查看JSONObject.toString(int)
和JSONObject.toString()
的实施情况:
public String toString(int indentFactor) throws JSONException {
StringWriter w = new StringWriter();
synchronized (w.getBuffer()) {
return this.write(w, indentFactor, 0).toString();
}
}
write
方法写入Writer
并将任何IOException重新抛出为JSONException。如果你的分析是正确的,那么这样的IOException永远不会发生,因为StringWriters也不会抛出IOExceptions。所以这似乎只是一个实现决定让这个方法抛出一个JSONException并且文档有误导性。
public String toString() {
try {
return this.toString(0);
} catch (Exception e) {
return null;
}
}
toString()
实现证实了这一分析:API设计者决定捕获任何异常,只有在异常永远不会抛出时才会有意义。
将try-catch
移动到toString(int)
以从签名中的throw子句释放两个方法可能会更好。
答案 2 :(得分:0)
我刚遇到这个问题。
以下示例将导致JSONObject.toString(int)
方法抛出JSONException
:
public static void main(String[] args) {
Map<String, Double> map = new HashMap<>();
map.put("num", Double.NaN);
JSONObject obj = new JSONObject();
obj.put("map", map);
obj.toString(0);
}
在我看来,JSONObject.put()
方法应该抛出异常,但显然没有在这里进行检查......