当前位置: 首页 > 知识库问答 >
问题:

JsonPath表达式来查找一组JSON对象中是否不存在键值对?

聂和宜
2023-03-14

给定以下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来查找记录数组下的任何对象是否缺少到期日键和值对。我目前有一个可行的解决方案,它使用一种方法,将记录的所有条目添加到一个列表中,将到期日的所有条目添加到另一个列表中,并简单地检查两个列表大小的减法是否等于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表达式 分隔符,这会导致一些我希望避免的其他无关问题:

$。完整报告。历史记录[?(@.到期日)];$。完整报告。历史记录[*]

对于XML中这种确切结构的副本,我可以使用XPath表达式,如下所示:布尔(full_report/历史/记录[不(expiry_date/文本())])

有没有可能在JsonPath中遗漏了一个等效的过滤器?

使现代化

Saeed Alizadeh使用谓词给出的以下答案并不能解决必须首先传递属性才能查找的问题。

它确实有助于使方法和属性的传递更加清晰,因为不再需要编写两个单独的表达式而不是表达式;属性到查找。从下面的方法中可以看出,这一基本问题仍然存在,但更容易解决:

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

我不想为属性的方法添加第三个参数,也不想分割传入字符串来回避这个问题,因为在endpoint处提供JsonPath表达式作为输入时,它会产生一些问题。如果不存在类似XPath示例的单行表达式,我将把这个问题标记为Saeed所回答的问题。


共有1个答案

曹和正
2023-03-14

如下所示,通过使用谓词,您可以过滤结果:

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Predicate;

import java.util.List;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        String json = "{\n" +
                "  \"full_report\": {\n" +
                "    \"score\": \"5\",\n" +
                "    \"history\": {\n" +
                "      \"record\": [\n" +
                "        {\n" +
                "          \"name\": \"John Smith\",\n" +
                "          \"SSN\": \"123456789\",\n" +
                "          \"last_visit\": \"02.03.2019\",\n" +
                "          \"expiry_date\": \"15.03.2019\"\n" +
                "        },\n" +
                "        {\n" +
                "          \"name\": \"John Doe\",\n" +
                "          \"SSN\": \"987654321\",\n" +
                "          \"last_visit\": \"05.03.2019\",\n" +
                "          \"expiry_date\": \"15.09.2019\"\n" +
                "        },\n" +
                "        {\n" +
                "          \"name\": \"Jane Doe\",\n" +
                "          \"SSN\": \"999999999\",\n" +
                "          \"last_visit\": \"02.03.2019\"\n" +
                "        }\n" +
                "      ]\n" +
                "    }\n" +
                "  }\n" +
                "}";
        Predicate expiry_date = new Predicate() {
            public boolean apply(PredicateContext predicateContext) {
                Object expiry_date = predicateContext.item(Map.class).get("expiry_date");
                return expiry_date != null && expiry_date.toString().length() > 0 ? false : true;
            }
        };
        List records = JsonPath.parse(json).read("full_report.history.record[?]", List.class, expiry_date);
        System.out.println(records);
    }
}

这将打印以下输出,作为缺少“到期日”属性的唯一记录

[{"name":"Jane Doe","SSN":"999999999","last_visit":"02.03.2019"}]

更新

public static boolean isMissing(String json, final String jsonProperty) {
    Predicate predicate = new Predicate() {
        public boolean apply(PredicateContext predicateContext) {
            Object propertyObject = predicateContext.item(Map.class).get(jsonProperty);
            return propertyObject != null && propertyObject.toString().length() > 0 ? false : true;
        }
    };
    List records = JsonPath.parse(json).read("full_report.history.record[?]", List.class, predicate);
    return (records != null && records.size() > 0) ? true : false;
}

输出:

System.out.println(isMissing(json, "expiry_date")); // prints true
System.out.println(isMissing(json, "name")); // prints false
 类似资料:
  • 上面是我正在处理的JSON对象。我想检查键是否存在。我尝试了下面的代码,但它不起作用。有办法实现吗?

  • 问题内容: 我有下一个JSON: 知道JSON对象中是否存在“ dog”值的最佳方法是什么? 谢谢。 解决方案1 解决方案2(JQuery) 解决方案3(使用some()方法) 问题答案: JSON变量引用具有一个称为“名称”的属性的对象数组。我不知道最好的方法,但这就是我的工作吗?

  • 以下是我的示例功能文件: 有没有一种方法可以使用空手道表达式检查状态是主动还是不主动? 注意:它肯定可以通过编写托管JS函数来实现。

  • 我有一个JSON对象,如下所示: 我想检查是否存在一个值为“id2”的id,java中是否有任何UTIL允许我这样做,而无需遍历所有对象并将字符串与目标进行比较? 附言:我不想知道“id”字段是否存在,使用JSONObject.has(键),这不是我要问的。

  • 问题内容: 如何检查JavaScript对象或数组中是否存在特定键? 如果密钥不存在,而我尝试访问它,它将返回false吗?还是抛出错误? 问题答案: 检查不确定性不是测试密钥是否存在的准确方法。如果密钥存在但值实际上是怎么办? 您应该改为使用运算符: 如果要检查密钥是否不存在,请记住使用括号: 或者,如果您要特别测试对象实例的属性(而不是继承的属性),请使用: 有关和的方法之间的性能比较,关键是

  • 如果我有以下对象数组: 是否有一种方法可以在数组中循环,以检查特定用户名值是否已经存在,如果它什么也不做,但如果它不做,则使用所述用户名(和新ID)向数组中添加一个新对象? 谢谢!