过滤 JSON 个包含部分数组的文件

Filter for JSON files that contain part of an array

我有一个功能允许我使用另一个 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

欢迎提供任何帮助。

您的代码

if (fileEntries.containsAll(filterRules)) {

检查文件是否包含 equal 元素,因此,对于数组,它检查数组是否 equal,而不是是否一个包含另一个的元素。

在 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.[=14 中的所有元素=]

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