【问题标题】:JSONArray.accumulate method in Java doesn't return arrays of oneJava中的JSONArray.accumulate方法不返回一个数组
【发布时间】:2021-10-08 07:40:26
【问题描述】:

我正在尝试将值累积到 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 会构建一个在数组中的简单字符串。

我得到了什么:

“颜色”:[“红色”,“绿色”,“蓝色”]

“形状”:[“椭圆”,“三角形”]

“心情”:“开心”

我想要什么:

“颜色”:[“红色”,“绿色”,“蓝色”]

“形状”:[“椭圆”,“三角形”]

“心情”:[“快乐”]

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

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

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

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

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

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

【问题讨论】:

标签: java arrays json pdi accumulate


【解决方案1】:

accumulate 方法会在 key 缺失或null 的情况下直接存储值,但如果那里已经有一个空数组,它会将值追加到数组中。所以,你应该可以通过在调用累加之前移动空数组的创建来获得你想要的行为,例如:

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

【讨论】:

  • 谢谢蒂姆,但这似乎有一些副作用,或者我做错了两件事? (Java 新手。)该值现在像"Mood": ["happy", "happy", "happy", "sad", "sad", "happy"] 一样重复,而通常累积忽略重复项。此外,每条记录的输出都相同。也许这与这样一个事实有关,这个函数自然会在一个循环中被多次调用?但我仍然无法弄清楚累积是如何停止忽略重复的。这就是累积与看跌的重点。
  • 我编辑了这个问题,以便更清楚地了解我如何调用该函数,以防万一。
【解决方案2】:

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

但我非常有兴趣(并且为了后代)了解这是否是一种有效的方法,或者是否有更好的方法来完成这项工作(可读性或执行速度)?

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    • 2015-12-07
    • 2014-12-14
    • 1970-01-01
    • 2016-04-05
    • 2020-02-21
    相关资源
    最近更新 更多