2017-09-15 9 views
4

다른 JSON 객체를 필터로 사용하여 특정 JSON 파일을 필터링 할 수있는 기능이 있습니다.배열의 일부를 포함하는 JSON 파일에 대한 필터

참조 코드 : 내가 할 노력하고있어

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

배열 오브젝트는 오브젝트 1 포함 된 모든 파일을 필터링 할 수 있습니다 :

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을 상상해보십시오. 나는 객체 2에 대해 신경 쓰지 않는다. 적어도 객체 배열에있는 객체 1을 가진 파일들을 필터링하고 싶다.

아무것도 결과 아래의 코드 :

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 

어떤 도움이 appriciated됩니다.

답변

2

, 그것은 배열 동일, 아닌지 확인 하나가 다른 하나의 요소를 포함하는지 여부.

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); 
} 

은 내가 element JSON의 배열이 predicate JSON의 모든 요소가 포함되어 있는지 여부를 확인하기 위해 스트림 API를 사용했다.

이 코드는 중첩 된 객체를 처리하므로 배열이 루트 수준에 있지 않은 경우에도 여전히 작동합니다. 그러나 배열 자체에 객체가 포함되어 있으면 객체는 동일해야합니다.

+0

늦게 응답 해 주셔서 감사합니다. 나는 기본적으로 전체 필터에있는 배열을이 함수에 넣을 것입니다. –

+0

'predicate'은 배열 인 여러 필드를 가진'JsonObject' 일 수 있습니다. – izstas

0

현재 키 값 쌍을 비교하여 같음을 확인하는 것처럼 보이므로 objects 키의 값을 비교하는 것이 좋습니다.

내가하려는 것은 배열 객체 에 object1이 들어있는 모든 파일을 필터링하는 것입니다.

objects 키에 액세스하여 값을 비교하십시오.

뭔가 파일이 배열의 경우, 동일한 요소가 포함되어 있으므로

if (fileEntries.containsAll(filterRules)) { 

확인 여부를 귀하의 코드

처럼
Gson gson = new Gson(); 

// Filter object rule 
List<JsonElement> objectRules = gson.fromJson(filter.get("objects"), ArrayList.class); 
// Compare the files with the given object filter 
List<JsonElement> objectEntries = gson.fromJson(entry.getKey().get("objects"), ArrayList.class); 

if (objectEntries.containsAll(objectRules)) {...}