Учитывая следующее JSON:
{
"full_report": {
"score": "5",
"history": {
"record": [
{
"name": "John Smith",
"SSN": "123456789",
"last_visit": "02.03.2019",
"expiry_date": "15.03.2019"
},
{
"name": "John Doe",
"SSN": "987654321",
"last_visit": "05.03.2019",
"expiry_date": "15.09.2019"
},
{
"name": "Jane Doe",
"SSN": "999999999",
"last_visit": "02.03.2019"
}
]
}
}
}
Я хотел бы иметь возможность использовать JsonPath , чтобы найти, если какой-либо из объектов в массиве записей отсутствует expiry_date
ключ и значение пары. В настоящее время у меня есть рабочее решение, использующее метод, который добавляет все записи record
в один список и все записи expiry_date
в другой и просто проверяет, равно ли вычитание обоих размеров списка 0, чтобы вернуть логическое значение.
public Boolean isMissing(String json, String expression) {
String[] expr = expression.split(";");
List<String> totalRecords = JsonPath.read(json, expr[0]);
List<String> foundRecords = JsonPath.read(json, expr[1]);
return totalRecords.size() - foundRecords.size() != 0;
}
Для этого необходимо использовать два выражения JsonPath с разделителем ;
, таким образом, что вызывает некоторые другие, не связанные с этим проблемы, которых я бы хотел избежать:
$.full_report.history.record[?(@.expiry_date)];$.full_report.history.record[*]
Для копии этой точной структуры в XML я могу использовать выражение XPath, например, так: boolean(full_report/history/record[not(expiry_date/text())])
Есть ли шанс, что есть эквивалентный фильтр, который я мог пропустить в JsonPath?
Обновление
Ответ Саида Ализаде, приведенный ниже для использования предиката, не решает проблему необходимости передавать свойство для поиска в первую очередь.
Это помогло сделать метод и передать свойство более понятным, поскольку больше нет необходимости писать два отдельных выражения вместо expression;property_to_lookup
. Как видно из метода, приведенного ниже, эта фундаментальная проблема все еще остается, но она намного проще:
public Boolean isMissing(String json, String expression) {
String[] expressionAndPredicate = expression.split(";");
Predicate missingKeyValue = predicateContext -> {
Object missingKey = predicateContext.item(Map.class).get(expressionAndPredicate[1]);
return missingKey == null || missingKey.toString().length() <= 0;
};
List<String> records = JsonPath.read(json, expressionAndPredicate[0], missingKeyValue);
return records.size() != 0;
}
Я не хочу добавлять третий метод в метод для свойства или разбивать входящую строку обойти проблему, поскольку это создает некоторые проблемы при предоставлении выражения JsonPath в качестве входных данных в конечной точке. Если не существует однострочного выражения, подобного примеру XPath, я отмечу вопрос как ответ от Саида.