简体   繁体   English

JSONObject.toString(int)如何抛出JSONException?

[英]How can JSONObject.toString(int) throw JSONException?

I noticed this in the JSONObject.toString(int) documentation 我在JSONObject.toString(int)文档中注意到了这一点

Throws: JSONException - If the object contains an invalid number. 抛出:JSONException - 如果对象包含无效的数字。

How could the object contain an invalid number if the NaN/Infinity check is done beforehand (either at parsing and in statements like .put("blah", Double.NAN) ? Which statements would throw that exception? 如果NaN / Infinity检查事先完成(在解析和语句如.put("blah", Double.NAN) ,对象如何包含无效数字?哪些语句会引发该异常?

I also read in the docs that .toString() without args doesn't throw anything, so I thought that the exception could be related to the integer passed as parameter; 我还在文档中读到没有args的.toString()不会抛出任何东西,所以我认为异常可能与作为参数传递的整数有关; but even with zero, negative or Integer.MAX/MIN_VALUE it still works. 但即使有零,负或Integer.MAX / MIN_VALUE它仍然有效。

So when one should expect .toString(int) to throw an exception and how should one handle that? 所以当人们应该期望.toString(int)抛出异常时应该如何处理?

toString() method not throws an exception because it has to override a signature of public void toString() method of java.lang.Object . toString()方法不会抛出异常,因为它必须覆盖java.lang.Objectpublic void toString()方法的签名。 In org.json.JSONObject generic toString() method actually fails silently since the source code is: 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>&nbsp;<small>(left
 *         brace)</small> and ending with <code>}</code>&nbsp;<small>(right
 *         brace)</small>.
 */
public String toString() {
    try {
        return this.toString(0);
    } catch (Exception e) {
        return null;
    }
}

This method relies on toString(int) method, and in case that it throws the exception, it catch it and returns null. 此方法依赖于toString(int)方法,并且在它抛出异常的情况下,它会捕获它并返回null。

According to the toString(int) description, the exception is thrown when org.json.JSONObject has an invalid number inside one of its elements; 根据toString(int)描述,当org.json.JSONObject在其中一个元素中包含无效数字时,抛出异常; but looking at code could be possible that this exception is thrown for other reasons. 但是查看代码可能会因为其他原因而抛出此异常。

When you use toString(int) the stack trace finally calls write() method to parse the object itself, the exception could be thrown for some of transformations from json objects to string: 当你使用toString(int) ,堆栈跟踪最终调用write()方法来解析对象本身,对于从json对象到string的一些转换,可能抛出异常:

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

However if as you said in your question (and @Carlos Rodriguez comments) all the checks are performed when the object is created, probably toString(int) method never thrown an exception. 但是,正如您在问题中所说(以及@Carlos Rodriguez评论)所有检查都是在创建对象时执行的,可能toString(int)方法永远不会抛出异常。

Hope it helps, 希望能帮助到你,

It helps to look at the implementation of JSONObject.toString(int) and JSONObject.toString() : 它有助于查看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();
    }
} 

The write method writes to a Writer and rethrows any IOException as JSONException. write方法写入Writer并将任何IOException重新抛出为JSONException。 If your analysis is right, then such an IOException would never occur, since StringWriters also don't throw IOExceptions. 如果您的分析是正确的,那么这样的IOException将永远不会发生,因为StringWriters也不会抛出IOExceptions。 So it seems merely an implementation decision to let this method throw an JSONException and the documentation is misleading. 所以这似乎只是一个实现决定让这个方法抛出一个JSONException并且文档是误导性的。

public String toString() {
    try {
        return this.toString(0);
    } catch (Exception e) {
        return null;
    }
} 

The toString() implementation confirms this analysis: Here the API designers decided to catch any Exception which would only make sense if an Exception is never thrown. toString()实现确认了这一分析:API设计者决定捕获任何Exception,只有在永远不会抛出Exception时才会有意义。

It would have probably been better to move the try-catch into the toString(int) to free both method from the throw clause in their signatures. try-catch移动到toString(int)可能更好,以便从签名中的throw子句中释放两个方法。

I've just run into this problem. 我刚遇到这个问题。

Here is an example that will cause the JSONObject.toString(int) method to throw a JSONException : 下面是一个示例,它将导致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);
}

In my opinion the exception should be thrown by the JSONObject.put() method, but apparently no check is done here... 在我看来, JSONObject.put()方法应抛出异常,但显然这里没有检查...

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

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