Ну, это просто, вы не выполняете итерацию достаточно глубоко (список полей находится на третьем уровне). Если вы знаете структуру вашего 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;
}
}
Однако я бы сказал, что проще позволить Джексону сериализовать JSON в удобные данные структура, и вы просто используете геттеры POJO для получения ваших значений. Это также сделало бы это более понятным, чем обработка JsonNode
.
Просто к вашему сведению, я немного отредактировал ваши JSON и использовал Java 8 преобразований SAM для создания итераций для циклов foreach из итераторов, но вы все равно можете использовать свой код и повторить еще один уровень, используя while
и итераторы.