我有一个像这样的深度嵌套的 JsonObject,在这个对象中搜索特定值(本例中为 null)的最佳方法是什么?
{
"monitors" : ["monitor1"],
"index" : [{
"patterns" : [ "*" ],
"masked" : [ "abcd", "*ip_dest*::/[0-9]{1,3}$/::XXX"],
"allowed" : [ "123", null ]
}],
"permissions" : [ ]
}
对于此示例,我有一个键列表,我想获取这些键的值,检查该值是否具有 Array
类型,如果是,则搜索其中是否存在 null
那个数组。这是我的代码:
for (Entry<String, DataType> allowedKey : allowedKeys.entrySet()) {
DataType dataType = allowedKey.getValue();
JsonNode value = contentAsNode.get(allowedKey.getKey());
if (dataType == DataType.ARRAY && value != null) {
try {
List contentArray = DefaultObjectMapper.objectMapper.convertValue(value, java.util.List.class);
if (contentArray.contains(null)) {
this.errorType = ErrorType.NULL_ARRAY_ELEMENT;
return false;
}
} catch (Exception e) {
this.errorType = ErrorType.BODY_NOT_PARSEABLE;
return false;
}
}
}
但是在这种情况下 contains()
找不到 null
,因为我有一个嵌套数组。由于 Json 对象的结构每次都可能不同(它可能有嵌套数组或映射或只是一个数组),我想知道解析深度嵌套的 JsonObject 以找到特定值的最佳方法是什么?
更多说明:在上面的例子Json中,我感兴趣的键是index
,这个键的值是一个映射(但它也可以是一个数组或嵌套数组,我们做事先不知道),我想检查 null
值中是否有任何 index
(在这种情况下,有一个空值)
答案 0 :(得分:0)
使用 JSONPath 的一个可行的简单解决方案
public static void main(String[] args) {
String json = "{\r\n" +
" \"monitors\" : [\"monitor1\"],\r\n" +
" \"index\" : [{\r\n" +
" \"patterns\" : [ \"*\" ],\r\n" +
" \"masked\" : [ \"abcd\", \"*ip_dest*::/[0-9]{1,3}$/::XXX\"],\r\n" +
" \"allowed\" : [ \"123\", null ]\r\n" +
" }],\r\n" +
" \"permissions\" : [ ]\r\n" +
"}" ;
String path = "$.index[?(null in @.allowed)]"; //Check if allowed List has null value i.e. index->allowed
DocumentContext jsonContext = JsonPath.parse(json);
List<?> list = jsonContext.read(path);
if(list.isEmpty()) { //Based on empty List u can return true or false
System.out.println("Not found");
}else {
System.out.println("Found");
}
}
根据 OP 要求,提出另一个解决方案以递归方式遍历 JsonObject
public static void main(String[] args) {
String json = "{\r\n" +
" \"monitors\" : [\"monitor1\"],\r\n" +
" \"index\" : [{\r\n" +
" \"patterns\" : [ \"*\" ],\r\n" +
" \"masked\" : [ \"abcd\", \"*ip_dest*::/[0-9]{1,3}$/::XXX\"],\r\n" +
" \"allowed\" : [ \"123\", null ],\r\n" +
" \"country\" : \"India\"\r\n" +
" }],\r\n" +
" \"permissions\" : [ ]\r\n" +
"}" ;
try {
iterateJson(new JSONObject(json));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void iterateJson(JSONObject jsonObject) throws Exception {
ObjectMapper mapper = new ObjectMapper();
Iterator<String> iterator = jsonObject.keys();
while(iterator.hasNext()) {
String key = iterator.next();
if(jsonObject.get(key) instanceof JSONArray) {
JSONArray jsonArray = jsonObject.getJSONArray(key);
for(int i=0; i<jsonArray.length(); i++) {
if(jsonArray.get(i) instanceof JSONObject) {
iterateJson(jsonArray.getJSONObject(i));
}else if(jsonArray.get(i) instanceof String){
List<String> list = mapper.readValue(jsonArray.toString(), new TypeReference<List<String>>() {});
System.out.println(key+" :: "+list);
System.out.println("Contains null :: "+list.contains(null));
System.out.println();
break;
}
}
}else if(jsonObject.get(key) instanceof JSONObject) {
iterateJson(jsonObject.getJSONObject(key));
}
}
}
输出
masked :: [abcd, *ip_dest*::/[0-9]{1,3}$/::XXX]
Contains null :: false
allowed :: [123, null]
Contains null :: true
patterns :: [*]
Contains null :: false
monitors :: [monitor1]
Contains null :: false