简体   繁体   English

使用 Jackson 从 ObjectNode 获取嵌套的 JSON 元素

[英]Get nested JSON elements from ObjectNode using Jackson

I have an ObjectNode, that looks as follows我有一个 ObjectNode,如下所示

    {
     "Header":{
       "sub-header1":{
          "#field":"value",
          "#field":"value",

       },
       "sub-header2":{
          "field":"",
          "field":"",
          "field":"",
          "panel_field":{
            "value":"",
            "value":""
         }
      }          
   }

Now, what I want to do is to get all the fields from sub-headers in a list.现在,我想要做的是从列表中的子标题中获取所有字段。 This is the method that I'm employing这是我正在使用的方法

public static List<String> getDocumentFields(ObjectNode jsonDocumentNode) {        
    List<String> documentFields = new ArrayList<>();
    Iterator<JsonNode> fields = jsonDocumentNode.elements();
    while (fields.hasNext()) {
        JsonNode jsonNode = fields.next();
        Iterator<Map.Entry<String, JsonNode>> jsonFields = jsonNode.fields();
        while (jsonFields.hasNext()) {
            Map.Entry<String, JsonNode> jsonNodeEntry = jsonFields.next();
            documentFields.add(jsonNodeEntry.getKey());
        }
    }
    return documentFields;
}

But, I'm only getting headers in the list like {sub-header1, sub-header2} , instead of fields.但是,我只在列表中获取标题,例如{sub-header1, sub-header2} ,而不是字段。 How can I fix this?我怎样才能解决这个问题? I'd really appreciate any kind of help.我真的很感激任何形式的帮助。

EDIT: While @sfiss 's answer helped a great deal, I still wanted to find a way to do so without hardcoding the loop-logic and this answer turned out to be the exact thing I was looking for.编辑:虽然@sfiss的回答有很大帮助,但我仍然想找到一种方法来做到这一点,而无需对循环逻辑进行硬编码,结果这个答案正是我正在寻找的。

Well, it's simple, you are not iterating deep enough (field list is on third level).嗯,这很简单,你迭代的不够深(字段列表在第三层)。 If you know the structure of your JSON, just iterate until you find the desired fields:如果您知道 JSON 的结构,只需迭代直到找到所需的字段:

public class MyTest {

    @Test
    public void testJson() throws IOException {
        final String json = getJson();
        final JsonNode jsonDocumentNode = new ObjectMapper().readTree(json);
        final List<String> fields = getDocumentFields((ObjectNode) jsonDocumentNode);
        assertThat(fields, Matchers.contains("#field1", "#field2", "field1", "field2", "field3", "panel_field"));
    }

    public static String getJson() {
        return "{\r\n" +
                "     \"Header\":{\r\n" +
                "       \"sub-header1\":{\r\n" +
                "          \"#field1\":\"value\",\r\n" +
                "          \"#field2\":\"value\"\r\n" +
                "       },\r\n" +
                "       \"sub-header2\":{\r\n" +
                "          \"field1\":\"\",\r\n" +
                "          \"field2\":\"\",\r\n" +
                "          \"field3\":\"\",\r\n" +
                "          \"panel_field\":{\r\n" +
                "            \"value1\":\"\",\r\n" +
                "            \"value2\":\"\"\r\n" +
                "         }\r\n" +
                "      }          \r\n" +
                "   }\r\n" +
                "}";
    }

    public static List<String> getDocumentFields(final ObjectNode jsonDocumentNode) {
        final List<String> documentFields = new ArrayList<>();
        for (final JsonNode header : (Iterable<JsonNode>) jsonDocumentNode::elements) {
            for (final JsonNode subheader : (Iterable<JsonNode>) header::elements) {
                for (final Map.Entry<String, JsonNode> field : (Iterable<Map.Entry<String, JsonNode>>) subheader::fields) {
                    documentFields.add(field.getKey());
                }
            }
        }
        return documentFields;
    }
}

However, I would argue that it is simpler to let jackson serialize the JSON into a convenient data structure, and you just use the POJO's getters to obtain your values.但是,我认为让 jackson 将 JSON 序列化为方便的数据结构更简单,您只需使用 POJO 的 getter 来获取您的值。 That would also make it more clear than handling the JsonNode .这也比处理JsonNode更清楚。

Just FYI, I edited your JSON slightly and used Java 8 SAM conversions to create iterables for the foreach-loops from the iterators, but you can still use your code and iterate one more level using while and iterators.仅供参考,我稍微编辑了您的 JSON,并使用 Java 8 SAM 转换为迭代器的 foreach 循环创建可迭代对象,但您仍然可以使用您的代码并使用while和迭代器再迭代一个级别。

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

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