如何获取JSON中子元素的父元素名称?

时间:2019-01-29 13:07:53

标签: java json jackson

我有一些动态JSON,在处理之前我不知道其完整结构。

但是,我知道JSON可能包含某些嵌套的有趣元素。

e。对于此示例有效负载


{
  "id": "3334343",
  "contractor": {
    "ppsNo": "123334"
  },
  "fullTimeStaff":{
    "ppsNo": "343434"
  }
}

我想找到所有包含名为 ppsNo 的元素的外部元素的名称。

我尝试使用 root.findParents(“ ppsNo”),但这给了我ppsNo元素,而不是 contractor 的外部(父)元素我感兴趣的fullTimeStaff

    ObjectMapper objectMapper = new ObjectMapper();
    String payload = "{\n" +
            "  \"id\": \"3334343\",\n" +
            "  \"contractor\": {\n" +
            "    \"ppsNo\": \"123334\"\n" +
            "  },\n" +
            "  \"fullTimeStaff\":{\n" +
            "    \"ppsNo\": \"123334\"\n" +
            "  }\n" +
            "}";

    JsonNode root = objectMapper.readTree(payload);

    List<JsonNode> nodes = root.findParents("ppsNo");

返回的JsonNodes是{"ppsNo":"123334"}元素,而不是外部包含节点(“ contractor”和“ fullTimeStaff”)。

有没有办法做到这一点?我已经看过使用JSON路径,但是我也看不出有一种明显的方法也可以使用它来获取真正的父元素(包含/包含)。

在此示例中,我使用杰克逊,但我对替代品持开放态度

3 个答案:

答案 0 :(得分:0)

我没有花很多时间来编写代码。

您在Regex中寻找的表达式是\{\n "ppsNo": "\w+"\n }(您可以使用链接https://regex101.com对其进行测试)。您应该做的是,当遇到此表达式时,该表达式开始倒退并读取“”中的第一个单词。希望对您有帮助

答案 1 :(得分:0)

JsonPath库中有一个选项,它返回整个匹配路径而不是值。因此,您可以执行以下操作:

Configuration conf = Configuration.builder().options(Option.AS_PATH_LIST).build();
List<String> pathList = JsonPath.using(conf).parse(payload).read("$..ppsNo");

/* Returns :
 * [
 *   "$['contractor']['ppsNo']",
 *   "$['fullTimeStaff']['ppsNo']"
 * ]
 */

您只需将结果解析为正确的类型,然后删除最后一个元素即可获得直接父级。

Pattern pattern = Pattern.compile("(?<!\\$\\[)(\\w+)(?!\\])");
pathList = pathList.stream().map(path -> {
    Matcher m = pattern.matcher(path.toString());
    return m.find() ? m.group(0) : null;
}).collect(Collectors.toList());
System.out.println(pathList); // [contractor, fullTimeStaff]

这是指向官方Jayway JsonPath Maven存储库的链接。

答案 2 :(得分:0)

我们可以在JsonNode.fields方法的帮助下使用递归来搜索目标父节点。

public class GetParentByChildName {
    public static void main(String[] args) throws IOException {

        ObjectMapper objectMapper = new ObjectMapper();
        String payload = "{                                      \n"
                + "  \"id\": \"3334343\",                        \n"
                + "  \"contractor\": {                           \n"
                + "    \"ppsNo\": \"123334\"                     \n"
                + "  },                                          \n"
                + " \"arr\": [                                   \n"
                + "    {                                         \n"
                + "      \"contractor2\": {                      \n"
                + "        \"ppsNo\": \"123334\"                 \n"
                + "      }                                       \n"
                + "    },                                        \n"
                + "    [                                         \n"
                + "      {                                       \n"
                + "        \"contractor3\": {                    \n"
                + "          \"ppsNo\": \"123334\"               \n"
                + "        }                                     \n"
                + "      }                                       \n"
                + "    ]                                         \n"
                + "  ],                                          \n"
                + "  \"fullTimeStaff\":{                         \n"
                + "    \"ppsNo\": \"123334\"                     \n"
                + "  }                                           \n"
                + "}                                               ";

        JsonNode root = objectMapper.readTree(payload);
        List<String> fieldNames = new ArrayList<String>();
        getParentName(root, "ppsNo", fieldNames);
        System.out.println(fieldNames);
    }

    private static void getParentName(JsonNode node, String targetChildName, List<String> fieldNames) {
        if (node.getNodeType() == JsonNodeType.ARRAY) {
            node.elements().forEachRemaining(x -> getParentName(x, targetChildName, fieldNames));
            return;
        }
        if (node.getNodeType() != JsonNodeType.OBJECT) {
            return;
        }
        node.fields().forEachRemaining(x -> {
            Iterator<String> iter = x.getValue().fieldNames();
            while (iter.hasNext()) {
                String fieldName = iter.next();
                if (fieldName.equals(targetChildName)) {
                    fieldNames.add(x.getKey());
                }
            }
            getParentName(x.getValue(), targetChildName, fieldNames);
        });
    }
}