【问题标题】:How to retrieve and update json array element without traversing entire json如何在不遍历整个json的情况下检索和更新json数组元素
【发布时间】:2018-03-16 02:24:58
【问题描述】:

我有一个非常复杂的json 结构。它包含许多 array elements 并且这些数组元素包含其他数组元素等等。 请参阅下面的json 树结构。

Json 树结构一:

Json 树结构-2:

正如上面用黄色突出显示的,我想更新“rdKey”字段的值。 我写了下面的代码,它工作得很好:

String json = "escaped string (as it's a big string, I can't put it here)";
JSONObject jsonObj = new JSONObject(json);

    if (jsonObj.has("responseMap")) {
        JSONObject responseMap = jsonObj.getJSONObject("responseMap");
        if (responseMap.has("ValueJson")) {
            JSONObject valueJson = responseMap.getJSONObject("ValueJson");
            if (valueJson.has("ticketBean_CM")) {
                JSONObject ticketBean_CM = valueJson.getJSONObject("ticketBean_CM");
                if (ticketBean_CM.has("addByGamma")) {
                    String addByGamma = ticketBean_CM.getString("addByGamma");
                    System.out.println(addByGamma);

                    if (addByGamma.equals("VCE")) {
                        if (responseMap.has("ScreenJson")) {
                            JSONObject screenJson = responseMap.getJSONObject("ScreenJson");
                            if (screenJson.has("sections")) {
                                JSONArray sectionArray1 = screenJson.getJSONArray("sections");
                                if (sectionArray1.length() > 0) {
                                    JSONObject section0 = sectionArray1.getJSONObject(0);
                                    if (section0.has("sections")) {
                                        JSONArray sectionArray2 = section0.getJSONArray("sections");
                                        if (sectionArray2.length() > 3) {
                                            JSONObject section6 = sectionArray2.getJSONObject(3);
                                            if (section6.has("sections")) {
                                                JSONArray sectionArray3 = section6.getJSONArray("sections");
                                                if (sectionArray3.length() > 1) {
                                                    JSONObject section8 = sectionArray3.getJSONObject(1);
                                                    if (section8.has("elements")) {
                                                        JSONArray elementsArray1 = section8
                                                                .getJSONArray("elements");
                                                        if (elementsArray1.length() > 0) {
                                                            JSONObject elements1 = elementsArray1.getJSONObject(0);
                                                            if (elements1.has("elements")) {
                                                                JSONArray elementsArray2 = elements1
                                                                        .getJSONArray("elements");
                                                                if (elementsArray2.length() > 4) {
                                                                    JSONObject elements2 = elementsArray2
                                                                            .getJSONObject(4);
                                                                    if (elements2.has("rdKey")) {
                                                                        System.out.println(
                                                                                elements2.getString("rdKey"));
                                                                        elements2.put("rdKey",
                                                                                "CircuitID(FullPartial)");
                                                                        System.out.println(
                                                                                elements2.getString("rdKey"));
                                                                        System.out.println(jsonObj.toString());
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

如果有更好的解决方案,我希望你们帮助我。我可以在不遍历整个 json 对象的情况下做到这一点(直到找到相关字段)吗?如果json 树结构发生更改,此解决方案将不起作用,它需要是静态的,作为此代码的成功场景。

请提出更好的解决方案。

【问题讨论】:

  • 你可以使用for loop for ["responseMap", "ValueJson", "ticketBean_CM" , ..., 4 ] 因为你的编码风格几乎相同
  • 我没有通过它,请你帮忙。
  • 您的结构中似乎有很多条件(如数组中的位置和一些列名)。这是一个特定的约束,就像你之后不需要那样的东西还是你需要经常通过这些数组?对于后者,我建议创建代表您的对象的 Java bean 以便于访问。否则,您可以创建自己的微型 API,以免重复“如果长度元素部分等”。
  • @Asoub :我需要经常检查这些数组,即在每次调用我的 API 时,我都需要更改“rdKey”的值。请您启发创建一个小型 API不再重复。
  • 对不起,我不清楚,我的意思是“经常”在代码方面:您是否有很多代码通过数组来获取/更新特定数据,例如您在上面发布的或者是它是你代码中唯一的地方吗?我会在anwser中详细说明

标签: java arrays json


【解决方案1】:

如果你想逃避 JSON 的遍历,那么你可以使用 JSONPointer,在同一个 org.json 库中可用。 例如:

String query = <json_pointer_query to element array>
JSONPointer pointer = new JSONPointer(query);
JSONObject elementsArrayJSON = (JSONObject) pointer.queryFrom(jsonObj);
elementsArrayJSON.put("rdKey","CircuitID(FullPartial)");

JSON 指针查询语言可参考:

https://www.rfc-editor.org/rfc/rfc6901

注意: JSON 指针非常基础,它不支持通配符。所以你需要确定元素名称,否则会抛出异常。

【讨论】:

  • 您似乎已经修改了 json 字符串以使其被 JSONPointer 接受,但我无法更改/修改输入 json,这是我从另一个进程中获得的。在您的字符串查询中。
  • 只是Query字符串的一个例子,可以做相应的修改
【解决方案2】:

如果您对使用哪个库很灵活,那么JsonPath 可能对您有用。

您可以使用以下代码使用“rdKey”更新所有“元素”:

JsonPath.parse(json).set("$..elements[?(@.rdKey)].rdKey", "CircuitID(FullPartial)").json()

【讨论】:

  • 我只需要更新“rdKey”的单个实例而不是全部。
  • 如果不需要对象中的json转换,Punit的建议是最短的。否则,您可以尝试使用 [Jackson][1] 的 ObjectMapper
  • 抱歉之前的评论不完整:如果不需要对象中的json转换,Punit的建议是最短的。可能您必须添加一些过滤器才能仅更改您 wqant 的这些 rdKey。否则,您可以尝试使用 Jackson (Example) 中的 ObjectMapper,但您必须使用对象构建完整的结构,读取它,在正确的位置进行更改,最后重写它......
  • @java4fun:我知道 Jackson API,但如果我想使用它,则需要创建与 json 结构匹配的 java 对象。而且会增加任务的复杂度。
  • @Punit 不需要,您可以使用 mapper.readValue(..., HashMap.class) 将 json 读取为对象映射
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多