LoginSignup
1
0

More than 1 year has passed since last update.

pythonでjsonpathを試す

Last updated at Posted at 2021-11-26

前書き

最近AWSの仕事が多く、aws-cliでdescribe系のコマンドを打ってます。
表示させるだけならシンプルですが、複雑な処理をさせたいので、pythonで個人用のラッパーツールを作りました。

作成中にdescribe系のメソッドで取得したjsonに対して何らかの方法でフィルターしたいと探したところ
jsonpathなるものをKode Kloudで発見したので試してみました。

参考にした記事、サイト

https://github.com/h2non/jsonpath-ng
https://qiita.com/takkii1010/items/0ce1c834d3a73496ccef
https://www.sukerou.com/2018/12/python-jsonxpathjsonpath.html
https://kodekloud.com/topic/lab-json-path-wild-cards/

jsonpathの使い方は上記のサイトかkodekloudの練習問題やればわかると思います。

本記事の内容

この投稿では上記サイトの内容を踏まえたうえで
実際に使った時に私がやりたかった事に対して、正解がすぐ出なかった点をメモしておきます。

サンプルのjson

※AWSのELBの取得結果を参考にサンプルとして記載しています。

samplejson = { "LoadBalancers": 
    [
        {
            "LoadBalancerArn": "hogeARN", 
            "DNSName": "hugaDNSname", 
            "State": {
                "Code": "active"
            }, 
            "AvailabilityZones": [
                {
                    "ZoneName": "hoge-region1", 
                    "SubnetId": "hoge-subnet1", 
                    "LoadBalancerAddresses": [100]
                },
                {
                    "ZoneName": "hoge-region2", 
                    "SubnetId": "fuga-subnet2", 
                    "LoadBalancerAddresses": [200]
                }
            ]
        },
        {
            "LoadBalancerArn": "hogeARN2", 
            "DNSName": "hugaDNSname2", 
            "State": {
                "Code": "active2"
            }, 
            "AvailabilityZones": [
                {
                    "ZoneName": "hoge-regionc3", 
                    "SubnetId": "hoge-subnet3", 
                    "LoadBalancerAddresses": [300]
                },
                {
                    "ZoneName": "hoge-regiona4", 
                    "SubnetId": "fuga-subnet4", 
                    "LoadBalancerAddresses": [400]
                }
            ]
        }
    ]
}

検証した事

最下層の要素でマッチさせて親の要素を取りたい

例えば、StateのCodeがactiveであることを条件にマッチさせたいとき、下記のような形でアクセスすると思います。
result = parse("$.LoadBalancers[?State.[*].Code == 'active']").find(samplejson)

list(result)[0].value
{'LoadBalancerArn': 'hogeARN', 'DNSName': 'hugaDNSname', 'State': {'Code': 'active'}, 'AvailabilityZones': [{...}, {...}]}
※$を条件式の前に書けば行けるかと思いましたが、取得できませんでした。
parse("$[?LoadBalancers.State.[*].Code =~ 'active']").find(samplejson)
[]

ただ、このアクセスの仕方だと取得したデータから最上位のLoadBalancersの要素が抜けてしまいます。
LoadBalancersの要素まで残した状態でデータが欲しければparentを使うそうです。

result = parse("$.LoadBalancers[?State.[*].Code == 'active'].`parent`.`parent`").find(samplejson)
list(result)[0].value
{'LoadBalancers': [{...}, {...}]}

マッチさせる条件を変数にしたい

これはpythonの変数展開になりますが、記載しておきます。

先ほどのStateがactiveになっている要素を取得する例だと、以下のような記載になります。

variable = "match_word"
result = parse("$.LoadBalancers[?State.[*].Code == '%s'].`parent`.`parent`" % (variable )).find(samplejson)

pythonの変数展開は他にもやり方がありましたが、これで通ったからまぁいいかなと・・

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0