筛选包含数组

时间:2017-09-15 18:47:22

标签: java arrays json filesystems contains

我有一个函数,允许我使用另一个JSON对象作为过滤器过滤掉某些JSON文件。

参见代码:

public Map<String, Entry<JsonObject, Long>> loadFilter(Coll<?> coll, JsonObject filter){
    // Create Ret
    Map<String, Entry<JsonObject, Long>> ret = null;

    // Get Directory
    File directory = getDirectory(coll);
    if ( ! directory.isDirectory()) return ret;

    // Find All
    File[] files = directory.listFiles(JsonFileFilter.get());

    // Create Ret
    ret = new LinkedHashMap<String, Entry<JsonObject, Long>>(files.length);

    // Filter rules
    Set<Map.Entry<String, JsonElement>> filterRules = filter.entrySet();

    // For Each Found
    for (File file : files)
    {
        // Get ID
        String id = idFromFile(file);

        // Get Entry
        Entry<JsonObject, Long> entry = loadFile(file);

        // Trying to fix a weird condition causing a NPE error
        if(entry == null) continue;
        if(entry.getKey() == null) continue;

        // Compare the files with the given filter
        Set<Map.Entry<String, JsonElement>> fileEntries = entry.getKey().entrySet();
        if (fileEntries.containsAll(filterRules)) {
            // Add found data to return list
            ret.put(id, entry);
        }
    }

    return ret;
}

想象一下,我有以下JSON:

{
    "objects": [
        "object1",
        "object2"
    ],
}

我要做的是过滤掉数组对象包含object1的所有文件。我不关心对象2,我希望过滤出对象数组中至少包含object1的文件。

以下代码不会产生任何结果:

JsonObject filter = new JsonObject();
JsonArray array = new JsonArray();
array.add(new JsonPrimitive("object1"));
filter.add("objects", array);
Map<String, Entry<JsonObject, Long>> result = loadFilter(coll, filter); // nothing

任何帮助都是适当的。

1 个答案:

答案 0 :(得分:2)

您的代码

if (fileEntries.containsAll(filterRules)) {

检查文件是否包含相等的元素,因此,在数组的情况下,它会检查数组是否相等,而不是包含另一个的元素。

没有本地方法可以在Gson中进行比较,因此必须在代码中完成。

我建议这样的解决方案:

private static boolean checkJsonPredicate(JsonElement element, JsonElement predicate) {
    if (predicate == null) {
        return true;
    }

    if (element == null || predicate.getClass() != element.getClass()) {
        return false;
    }

    if (predicate.isJsonObject()) {
        return predicate.getAsJsonObject().entrySet().stream()
                .allMatch(e -> checkJsonPredicate(element.getAsJsonObject().get(e.getKey()), e.getValue()));
    }

    if (predicate.isJsonArray()) {
        return StreamSupport.stream(predicate.getAsJsonArray().spliterator(), false)
                .allMatch(element.getAsJsonArray()::contains);
    }

    return predicate.equals(element);
}

我使用Stream API来检查element JSON中的数组是否包含predicate JSON中的所有元素。

此代码处理嵌套对象(因此即使您的数组不在根级别,它仍然可以工作)。但是,如果数组本身包含对象,则对象必须相等。