You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何处理含@符号的JSON-LD文档的JsonPath筛选问题

解决JsonPath筛选含@符号的JSON-LD字段问题

我明白你遇到的痛点了——JSON-LD里的@type、@id这类带@的字段,在JsonPath里直接用会踩坑,因为@在JsonPath里是特殊运算符(用来指代当前节点),不是字段名的一部分。下面给你一步步拆解解决方案:

核心问题:JsonPath对特殊字符键名的处理

当JSON键名包含@、$这类特殊字符时,不能直接写orderDelivery[@type],必须用单引号或双引号把键名包裹起来,告诉JsonPath这是一个字面量的键名,而不是语法符号。正确的写法是orderDelivery['@type'](Java里用单引号更方便,不用转义双引号)。

解决方案1:筛选orderDelivery[@type]匹配指定值的订单

先修正你的代码两个关键问题:

  1. 修复JsonPath的字段引用语法
  2. 解决InputStream只能读取一次的问题(原代码里第二次读流会为空)

修正后的完整代码:

JsonArray getOrdersByDeliveryType(String orderDeliveryType) throws NoOrdersForDriverFoundException { 
    // 先把流转换成字符串缓存,避免重复读取流导致的空内容问题
    String jsonContent;
    try (InputStream ordersAsStream = /* 你的文档读取逻辑,比如从文件/网络获取 */) {
        jsonContent = new String(ordersAsStream.readAllBytes(), StandardCharsets.UTF_8);
    } catch (IOException e) {
        throw new RuntimeException("Failed to load orders document", e);
    }

    // 用单引号包裹带@的字段名,修正JsonPath筛选规则
    Filter deliveryTypeFilter = Filter.filter(
        Criteria.where("orderDelivery['@type']").eq(orderDeliveryType)
    ); 
    // 执行筛选:$[*]表示所有根节点下的订单,[?]应用筛选器
    List<Map<String, Object>> filteredOrders = JsonPath.parse(jsonContent)
        .read("$[*][?]", deliveryTypeFilter); 

    if(filteredOrders == null || filteredOrders.isEmpty()) { 
        throw new NoOrdersForDriverFoundException(); 
    } 

    // 将筛选后的Map列表转换为JsonArray
    JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
    for (Map<String, Object> order : filteredOrders) {
        arrayBuilder.add(Json.createObjectBuilder(order));
    }
    return arrayBuilder.build(); 
}

解决方案2:筛选orderDelivery.provider.employee[@id]匹配指定ID的订单

同样的逻辑,只需要修改筛选器的路径即可:

JsonArray getOrdersByEmployeeId(String targetEmployeeId) throws NoOrdersForDriverFoundException { 
    String jsonContent;
    try (InputStream ordersAsStream = /* 你的文档读取逻辑 */) {
        jsonContent = new String(ordersAsStream.readAllBytes(), StandardCharsets.UTF_8);
    } catch (IOException e) {
        throw new RuntimeException("Failed to load orders document", e);
    }

    // 嵌套字段的筛选:同样用单引号包裹@id
    Filter employeeIdFilter = Filter.filter(
        Criteria.where("orderDelivery.provider.employee['@id']").eq(targetEmployeeId)
    ); 
    List<Map<String, Object>> filteredOrders = JsonPath.parse(jsonContent)
        .read("$[*][?]", employeeIdFilter); 

    if(filteredOrders.isEmpty()) { 
        throw new NoOrdersForDriverFoundException(); 
    } 

    JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
    for (Map<String, Object> order : filteredOrders) {
        arrayBuilder.add(Json.createObjectBuilder(order));
    }
    return arrayBuilder.build(); 
}

关键总结

  1. 特殊键名处理:所有带@、$等特殊字符的JSON键,在JsonPath中必须用['键名']或["键名"]包裹
  2. 流的复用问题:InputStream是一次性读取的,必须先转换成字符串或字节数组缓存,避免二次读取为空
  3. 结果转换:JsonPath返回的List<Map>需要手动转换成JsonArray,不能直接复用原流读取

内容的提问来源于stack exchange,提问作者viggis75

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:21:36