过滤 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 中的所有元素=]
此代码处理嵌套对象(因此即使您的数组不在根级别,它仍然可以工作)。但是,如果数组本身包含对象,则对象必须相等。
我有一个功能允许我使用另一个 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 中的所有元素=]
此代码处理嵌套对象(因此即使您的数组不在根级别,它仍然可以工作)。但是,如果数组本身包含对象,则对象必须相等。