操作Json 和 SelectTokens with JsonPath

本文介绍了如何使用JsonPath表达式及LINQ来查询复杂的JSON数据结构,包括基本的路径选择、条件过滤及数值计算等高级用例。通过具体的代码示例,展示了如何针对嵌套的JSON数据进行精确检索。
部署运行你感兴趣的模型镜像

JsonPath expression:

$ the root object
@ the current object
.. recursive descent
[]下标操作符
*通配符
?()filter 条件

JToken. SelectToken

 

SelectToken是JToken上的一个方法,它采用字符串路径到child token。如果在路径的位置找不到child token.,则SelectToken将返回子child token或空引用。 该路径由以句点分隔的属性名称和数组索引组成,e.g. Manufacturers[0].Name.

 

JObject o = JObject.Parse(@"{
  'Stores': [
    'Lambton Quay',
    'Willis Street'
  ],
  'Manufacturers': [
    {
      'Name': 'Acme Co',
      'Products': [
        {
          'Name': 'Anvil',
          'Price': 50
        }
      ]
    },
    {
      'Name': 'Contoso',
      'Products': [
        {
          'Name': 'Elbow Grease',
          'Price': 99.95
        },
        {
          'Name': 'Headlight Fluid',
          'Price': 4
        }
      ]
    }
  ]
}");

string name = (string)o.SelectToken("Manufacturers[0].Name");
// Acme Co

decimal productPrice = (decimal)o.SelectToken("Manufacturers[0].Products[0].Price");
// 50

string productName = (string)o.SelectToken("Manufacturers[1].Products[0].Name");
// Elbow Grease

JToken. SelectTokens with jsonPath

JObject o = JObject.Parse(@"{
  'Stores': [
    'Lambton Quay',
    'Willis Street'
  ],
  'Manufacturers': [
    {
      'Name': 'Acme Co',
      'Products': [
        {
          'Name': 'Anvil',
          'Price': 50
        }
      ]
    },
    {
      'Name': 'Contoso',
      'Products': [
        {
          'Name': 'Elbow Grease',
          'Price': 99.95
        },
        {
          'Name': 'Headlight Fluid',
          'Price': 4
        }
      ]
    }
  ]
}");

// manufacturer with the name 'Acme Co'
JToken acme = o.SelectToken("$.Manufacturers[?(@.Name == 'Acme Co')]");

Console.WriteLine(acme);
// { "Name": "Acme Co", Products: [{ "Name": "Anvil", "Price": 50 }] }

// name of all products priced 50 and above
IEnumerable<JToken> pricyProducts = o.SelectTokens("$..Products[?(@.Price >= 50)].Name");

foreach (JToken item in pricyProducts)
{
    Console.WriteLine(item);
}
// Anvil
// Elbow Grease

select Token with Linq

IList<string> storeNames = o.SelectToken("Stores").Select(s => (string)s).ToList();
// Lambton Quay
// Willis Street

IList<string> firstProductNames = o["Manufacturers"].Select(m => (string)m.SelectToken("Products[1].Name")).ToList();
// null
// Headlight Fluid

decimal totalPrice = o["Manufacturers"].Sum(m => (decimal)m.SelectToken("Products[0].Price"));
// 149.95

我在项目中遇到的问题是:model下面有很多id,我需要根据传入的多个id去找:

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

<think> 我们正在讨论如何使用JSONPath在Java中获取多级JSON的某个属性值。根据引用[1][2]的内容,我们知道JSONPath是一种强大的工具,可以用类似正则表达式的语法来提取JSON中的部分内容。在Java中,我们可以使用Jayway的JSONPath库来实现。 步骤: 1. 添加依赖:首先,需要在项目中添加json-path的依赖。 2. 使用JsonPath类的静态方法读取JSON字符串,通过指定JSONPath表达式来获取值。 示例: 假设我们有如下JSON字符串: ```json { "user": { "profile": { "name": "John", "address": { "city": "New York" } } } } ``` 我们想要获取city的值,对应的JSONPath表达式是:`$.user.profile.address.city` Java代码示例: ```java import com.jayway.jsonpath.JsonPath; import java.util.List; public class JsonPathExample { public static void main(String[] args) { String json = "{\"user\":{\"profile\":{\"name\":\"John\",\"address\":{\"city\":\"New York\"}}}}"; // 使用JSONPath读取city的值 String city = JsonPath.read(json, "$.user.profile.address.city"); System.out.println(city); // 输出: New York } } ``` 注意: - 如果路径可能不存在,可以使用`JsonPath.parse`并配合`try-catch`来处理异常。 - 如果路径对应的是一个数组,可以使用`List`来接收,例如:`List<String> cities = JsonPath.read(json, "$..city");` 这将获取所有层级的city值。 另外,如果JSON结构复杂,且存在多个同名的键,可以使用通配符过滤器: 例如,获取所有user下的profile的address中的city,可以使用:`$.user.profile.address[*].city` 或者 `$..city`(递归下降,匹配所有city)。 高级过滤: 例如,我们想获取所有年龄大于25岁的用户的姓名: ```java String json = ...; // 包含用户数组的JSON List<String> names = JsonPath.parse(json) .read("$.users[?(@.age > 25)].name"); ``` 依赖配置(Maven): ```xml <dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> <version>2.7.0</version> </dependency> ``` 注意:在编写JSONPath表达式时,可以使用在线工具(如:https://jsonpath.com/)进行测试。 引用[1]中指出JsonPath提供了类似正则表达式的语法,可以满足大部分需求[^1]。引用[2]中提到在解析失败时可能会抛出异常,因此在实际应用中需要做好异常处理[^2]。 如果路径不存在,JsonPath.read会抛出PathNotFoundException,因此建议使用以下方式安全获取: ```java Object city = JsonPath.parse(json).read("$.user.profile.address.city", Object.class); if (city != null) { // 处理city } ``` 或者使用默认值: ```java Configuration conf = Configuration.defaultConfiguration().addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL); String city = JsonPath.using(conf).parse(json).read("$.user.profile.address.city", String.class); // 如果路径不存在,city将为null ``` 这样,我们就能够安全地获取多级JSON中的属性值了。 </think> 在Java中获取多层级JSON特定属性的值,JSONPath是最简洁高效的解决方案。以下是详细使用方法: ### 核心实现步骤 #### 1. 添加Maven依赖 ```xml <dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> <version>2.8.0</version> </dependency> ``` #### 2. 基本取值方法 ```java import com.jayway.jsonpath.JsonPath; public class JsonPathDemo { public static void main(String[] args) { String json = "{\"store\":{\"book\":[{\"title\":\"Java指南\",\"price\":35},{\"title\":\"JSON解析\",\"price\":28}]}}"; // 获取第一本书的标题 String title = JsonPath.read(json, "$.store.book[0].title"); System.out.println(title); // 输出: Java指南 // 获取所有书籍价格 List<Double> prices = JsonPath.read(json, "$.store.book[*].price"); System.out.println(prices); // 输出: [35.0, 28.0] } } ``` #### 3. 路径表达式语法详解 | 表达式类型 | 示例 | 说明 | |----------------|------------------------------|--------------------------| | 根对象 | `$` | 根节点 | | 子属性 | `$.store.book[0].title` | 获取嵌套属性 | | 通配符 | `$.store.book[*].price` | 获取所有书籍价格 | | 递归搜索 | `$..price` | 获取所有层级的price属性 | | 数组切片 | `$.store.book[0:2]` | 获取前2本书 | | 条件过滤 | `$.store.book[?(@.price>30)]`| 获取价格>30的书籍 | ### 高级用法示例 #### 1. 条件过滤 ```java // 获取价格高于30的书籍标题 List<String> expensiveBooks = JsonPath .parse(json) .read("$.store.book[?(@.price > 30)].title"); ``` #### 2. 多层级通配 ```java // 获取所有层级的title属性 List<String> allTitles = JsonPath.read(json, "$..title"); ``` #### 3. 安全访问(避免空指针) ```java DocumentContext ctx = JsonPath.parse(json); Optional<String> safeResult = ctx .read("$.missing.path", Configuration.defaultConfiguration() .addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL)) .option(Options.AS_STRING); // 路径不存在返回null ``` #### 4. 类型转换 ```java // 显式指定返回类型 Double price = JsonPath.parse(json) .read("$.store.book[0].price", Double.class); ``` ### 性能优化建议 1. **解析缓存**:重复解析时缓存`DocumentContext`对象 ```java DocumentContext ctx = JsonPath.parse(json); // 只解析一次 String title = ctx.read("$.store.book[0].title"); ``` 2. **编译表达式**:高频访问时预编译JSONPath ```java JsonPath path = JsonPath.compile("$.store.book[0].price"); Double price = path.read(json); ``` 3. **惰性求值**:大JSON文件使用流式处理 ```java Configuration conf = Configuration.builder() .jsonProvider(new JacksonJsonProvider()) .options(Option.SUPPRESS_EXCEPTIONS).build(); Object value = JsonPath.using(conf).parse(json).read(path); ``` ### 异常处理 ```java try { return JsonPath.read(json, "$.deep.nested.value"); } catch (PathNotFoundException ex) { // 路径不存在处理 return defaultValue; } catch (InvalidJsonException ex) { // JSON格式错误处理 throw new RuntimeException("Invalid JSON", ex); } ``` JSONPath提供了类似正则表达式的强大语法,可以高效定位复杂JSON结构中的任意值[^1]。在路径解析失败时,建议使用`Option.DEFAULT_PATH_LEAF_TO_NULL`配置选项避免异常[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值