JSONArray.accumulate Java 中的方法不 return 一个数组

JSONArray.accumulate method in Java doesn't return arrays of one

我正在尝试将值累积到 JSONArray 中。 对于大多数数据,这都符合我的预期,例如使用我编写的函数(的简化版本)...

private void copyValidJsonArray(JSONObject objIn, String arrNameIn, JSONObject objOut, String arrNameOut) throws JSONException {
    // This function copies each item of a JSONArray named arrNameIn within objIn to another JSONArray named arrNameOut in objOut, creating arrNameOut if it doesn't exist there.
    
    if (objIn != null) {
        if (objOut == null)
            objOut = new JSONObject();
        JSONArray arrIn = objIn.optJSONArray(arrNameIn);
        if (arrIn != null && arrIn.length() > 0) {
            for (int i = 0; i < arrIn.length(); i++) {
                String valueIn = arrIn.get(i).toString();
                objOut.accumulate(arrNameOut, valueIn);
            }
        }
        if (!objOut.has(arrNameOut))
            objOut.put(arrNameOut, emptyJSONArray);
    }
}

...但是当只有一个 valueIn 被累加时,accumulate 会在数组中构建一个 not 的简单字符串。

我得到的:

"Colors": ["red","green","blue"]

"Shapes": ["oval","triangle"]

"Moods": "happy"

我想要的:

"Colors": ["red","green","blue"]

"Shapes": ["oval","triangle"]

"Moods": ["happy"]

研究这个问题,我发现我得到的是正确的和普遍期望的行为。 但是将读取我的输出的系统非常简单,并且每次都期望相同的结构。

搜索网络和堆栈溢出,我发现的一切都假设我想要默认行为,但我不能是唯一一个必须处理一心一意的下游系统的人,对吧? ;)

底线:无论传入多少值,我如何才能顺利地确保输出 JSONArray?

编辑:我正在这样调用函数...

copyValidJsonArray(inputData, "colours", outputData, "Colors");
copyValidJsonArray(inputData, "geo", outputData, "Shapes");
copyValidJsonArray(inputData, "moods", outputData, "Moods");

...每条记录运行一次,就像在 Pentaho (PDI) 中一样。

accumulate方法在缺少key或者null的情况下会直接存储值,但是如果那里已经有一个空数组,它会将值追加到数组中。因此,您应该能够通过在调用 accumulate 之前移动空数组的创建来获得所需的行为,例如:

private void copyValidJsonArray(JSONObject objIn, String arrNameIn, JSONObject objOut, String arrNameOut) throws JSONException {
    // This function copies each item of a JSONArray named arrNameIn within objIn to another JSONArray named arrNameOut in objOut, creating arrNameOut if it doesn't exist there.
    
    if (objIn != null) {
        if (objOut == null)
            objOut = new JSONObject();
        if (!objOut.has(arrNameOut))
            objOut.put(arrNameOut, emptyJSONArray);
        JSONArray arrIn = objIn.optJSONArray(arrNameIn);
        if (arrIn != null && arrIn.length() > 0) {
            for (int i = 0; i < arrIn.length(); i++) {
                String valueIn = arrIn.get(i).toString();
                objOut.accumulate(arrNameOut, valueIn);
            }
        }
    }
}

我不知道这是否是最佳解决方案,但它对我有用:请参阅注释为“改变累积输出以使用一个数组”的部分。

但我很想(也为了后代)想知道这是否是一种有效的方法,或者是否有更好的方法来完成这项工作(可读性或执行速度)?

private void copyValidJsonArray(JSONObject objIn, String arrNameIn, JSONObject objOut, String arrNameOut) throws JSONException {
    // This function copies each item of a JSONArray named arrNameIn within objIn to another JSONArray named arrNameOut in objOut, creating arrNameOut if it doesn't exist there.
    
    if (objIn != null) {
        if (objOut == null)
            objOut = new JSONObject();
        JSONArray arrIn = objIn.optJSONArray(arrNameIn);
        if (arrIn != null && arrIn.length() > 0) {
            for (int i = 0; i < arrIn.length(); i++) {
                String valueIn = arrIn.get(i).toString();
                objOut.accumulate(arrNameOut, valueIn);
            }
            // Alter the accumulated output to use arrays of one:
            if (objOut.has(arrNameOut)) {
                JSONArray arrOut = objOut.optJSONArray(arrNameOut);
                // If the structure created by accumulate is a String instead of an array of one...
                if (arrOut == null) {
                    String valueOut = objOut.optString(arrNameOut);
                    if (valueOut.length() > 0) {
                        // Remove the String and add it as an array of one:
                        objOut.remove(arrNameOut);
                        objOut.put(arrNameOut, new JSONArray().put(valueOut));
                    }
                }
            }
        }
        if (!objOut.has(arrNameOut))
            objOut.put(arrNameOut, emptyJSONArray);
    }
}