专业的JAVA编程教程与资源

网站首页 > java教程 正文

最强JSON查找工具——JmesPath(如何在json中查找数据)

temp10 2024-10-28 19:35:27 java教程 8 ℃ 0 评论

当我们从网站或者文件获取到复杂结构的 JSON 数据时, 是否因为其多层嵌套结构而头大, 当需要获取指定数据时,还需要写各种条件判断来处理这些取出的数据.

熟悉 Java 的一定使用过 JSONPath 来解析复杂结构的 json 数据, 而不需要解析为 Java 对象再从中获取对应的值.

最强JSON查找工具——JmesPath(如何在json中查找数据)

在 Python 也有相同的模块来支持该功能 -- JmesPath模块. 使用该模块, 可以使我们方便的处理复杂的数据结构.

如何使用

Jmespath 遵循自身的语法结构, 同时对 jsonpath 做了进一步扩展, 有 jsonpath 使用经验的可以快速上手.

# 安装 jmespath
pip install jmespath

# 导入 模块 
import jmespath

假如有以下数据

data = {
    "name": "小明",
    "age": 20,
    "hobby": {
        "sports": ["篮球", "足球"],
        "music": {
            "classical": ["小步舞曲", "致爱丽丝"],
            "pop": ["青花瓷", "七里香"]
        }
    }
}

使用传统的方式获取 pop 的第一首歌名

data["hobby"]["music"]["pop"][0]
# 青花瓷

使用 jmespath 获取, 逻辑结构更加清楚

jmespath.search("hobby.music.pop[0]", data)
# 青花瓷

到这里你可以能感觉使用 jmespath 获取数据和常规获取并没太大不同, 那就大错特错了, 这只是最基础的功能.使用下图为完整的语法结构(下方管道示例), 可以从复杂数据中筛选出可用数据, 极大地简化数据处理步骤:

过滤和多结果

jmespath 可以对数据做过滤以及获取多个结果内容, 并且将结果保存为列表或字典

data = {
  "people": [
    {
      "age": 20,
      "other": "foo",
      "name": "Bob"
    },
    {
      "age": 25,
      "other": "bar",
      "name": "Fred"
    },
    {
      "age": 30,
      "other": "baz",
      "name": "George"
    }
  ]
}

# 取people节点, ? 表示条件
# age > 20的结果中取name和age两个值, 保存为列表
jmespath.search("people[?age > `20`].[name, age]", data)
# 运行结果
[
  [
    "Fred",
    25
  ],
  [
    "George",
    30
  ]
]

# 同样的条件, 将结果保存为字典
jmespath.search("people[?age > `20`].{name: name, age: age}", data)
# 运行结果
[
  {
    "name": "Fred",
    "age": 25
  },
  {
    "name": "George",
    "age": 30
  }
]

通过简单的表达式语句, 就可以获取到结果, 相较于原始的需要做循环和条件判断, 非常容易的获取到想要的数据.

使用函数功能

除了使用表达式来过滤内容, jmespath 还提供非常丰富的内置函数对数据做处理, 比如排序(sort), 获取长度(length),计算(abs)等等

# 待处理数据
data = {
  "Contents": [
    {
      "Date": "2014-12-21T05:18:08.000Z",
      "Key": "logs/bb",
      "Size": 303
    },
    {
      "Date": "2014-12-20T05:19:10.000Z",
      "Key": "logs/aa",
      "Size": 308
    },
    {
      "Date": "2014-12-20T05:19:12.000Z",
      "Key": "logs/qux",
      "Size": 297
    },
    {
      "Date": "2014-11-20T05:22:23.000Z",
      "Key": "logs/baz",
      "Size": 329
    },
    {
      "Date": "2014-12-20T05:25:24.000Z",
      "Key": "logs/bar",
      "Size": 604
    },
    {
      "Date": "2014-12-20T05:27:12.000Z",
      "Key": "logs/foo",
      "Size": 647
    }
  ]
}

# 查找Contents内容, &Date表示Date做排序条件
# 结果整理为字典
jmespath.search(
  "sort_by(Contents, &Date)[*].{Key: Key, Size: Size}", 
  data)

# 运行结果
[
  {
    "Key": "logs/baz",
    "Size": 329
  },
  {
    "Key": "logs/aa",
    "Size": 308
  },
  {
    "Key": "logs/qux",
    "Size": 297
  },
  {
    "Key": "logs/bar",
    "Size": 604
  },
  {
    "Key": "logs/foo",
    "Size": 647
  },
  {
    "Key": "logs/bb",
    "Size": 303
  }
]

管道处理

使用 | 表示管道, 将前一个过滤后的结果传递给下一个条件, 通过管道处理, 我们可以逐一使用各种条件来筛选出数据, 最终得到想要的数据, 避免了再使用逻辑代码处理的流程

以下示例通过 3 个条件查找数据:

data = {
  "locations": [
    {"name": "Seattle", "state": "WA"},
    {"name": "New York", "state": "NY"},
    {"name": "Bellevue", "state": "WA"},
    {"name": "Olympia", "state": "WA"}
  ]
}

# 1. locations[?state == 'WA'].name 查找state为WA的内容, 
# 并取name值结果=>['Seattle', 'Bellevue', 'Olympia']

# 2. sort(@)[-2:] 对前边的结果排序, 并做切片
# 结果 => ['Olympia', 'Seattle']

# 3. {WashingtonCities: join(', ', @)}, 将结果整理为字典, 并用逗号分隔
# 结果 => {'WashingtonCities': 'Olympia, Seattle'}

jmespath.search(
"locations[?state == 'WA'].name | sort(@)[-2:] | {WashingtonCities: join(', ', @)}",
data)
# 运行结果
{
  "WashingtonCities": "Olympia, Seattle"
}

以上内容仅仅介绍了一些常用的功能, jmespath 可使用的功能远多于此处内容, 更多的操作可以到官网查看, 里边提供了详细的教程和示例, 不过内容没有中文版本.

#文章首发挑战赛#

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表