29
34

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【個人メモ】JSONのパースにjmespathを使ってみよう

Last updated at Posted at 2015-02-15

jmespath

Screen Shot 2015-02-15 at 19.10.37.png

JSONのパースには、jqというツールが有名である。
が、昨日、aws-cliにて、--query オプションにより
jmespath形式でのJSONパースを利用できる、ということで
jmespathそのものを試してみることにした。

jmespathをインストール

pipでインストールできる。

> pip install —user jmespath

インストール後、コマンドラインツールとしてjpコマンドを実行することが可能になる

> echo '{"a": "100"}' | jp a
“100"

簡単だ。

aws-cliでの出力を例に取りながら、
jmespathでのオプションをさらっと見ていく

JMESPath Tutorial

に書かれている。

例)aws-cliを利用してec2 instanceのprivate ipアドレスのみを取得してみる

管理している同立しているサービス向けのインスタンスの台数が30台〜とかなると
IPアドレスを抜くにも一苦労だったりする。

aws-cliでtext出力を行い、cutに食わせて出させる場合

aws ec2 describe-instances --filter "Name=tag:Role,Values=web-front" --output text | grep PRIVATEIPADDRESSES | cut -f3
10.0.1.1
10.0.1.2
10.0.1.3
10.0.1.4
10.0.1.5
...
10.0.1.50

こんな感じになってしまう。

jmespathを利用してaws-cliのJSON出力をパースするようにする

aws ec2 describe-instances --filter "Name=tag:Role,Values=web-front" --query "Reservations[*].Instances[*].PrivateIpAddress[]”

[
  “10.0.1.1”,
  “10.0.1.2”,
  “10.0.1.3”,
  “10.0.1.4”,
  “10.0.1.5”,
  …
  “10.0.1.50”
]

便利組み込み関数を利用してみる

aws cliがjmespathのクエリパスをサポートしているのは確認できた。
その他、jmespathに組み込まれているsearch関数を利用してみよう

search関数

search関数は表現力が高い。
Hashのキーマッチングやフィルタリングに対応している。

たとえば

以下のJSONデータがあるとする

[
  {
    "name": "Keiji Matsuzaki",
    "age": 33,
    "language":
    [
      "Japanese"
    ],
    "programming": {
        "language":
          [
            "PHP",
            "Python",
            "Go",
            "Ruby"
          ]
    }
  },
  {
    "name": "Fujisan Taro",
    "age": 24,
    "language":
    [
      "Japanese"
    ],
    "programming": {
        "language":
          [
            "Rust",
            "C++",
            "Erlang",
            "Go"
          ]
    }
  },
  {
    "name": "Lim Chow",
    "age": 28,
    "language":
    [
      "English",
      "Chinese"
    ],
    "programming": {
        "language":
          [
            "Ruby",
            "sass",
            "Lua",
            "C"
          ]
    }
  },
  {
    "name": "Jem Tomas",
    "age": 52,
    "language":
    [
      "English",
      "French"
    ],
    "programming": {
        "language":
          [
            "C",
            "BASIC",
            "NASM",
            "HTML",
            "Go",
            "Haskell"
          ]
    }
  }
]

ここから、以下の条件に合致するデータを取り出す

language: englishが含まれているレコードはどれぐらいあるか

jmespathでパースする場合はこうなる

jp -f test.json 'length([].language[?@==`English`][])'
> 2

どういうことか

[].language[] で、languageの要素を取得する。

[
    [
        "Japanese"
    ],
    [
        "Japanese"
    ],
    [
        "English",
        "Chinese"
    ],
    [
        "English",
        "French"
    ]
]

language[]のものから、current node == Englishに合致するものを検索する

[].language[?@==English]

[
    [],
    [],
    [
        "English"
    ],
    [
        "English"
    ]
]

arrayごとに分割されているのでflatten化する

[].language[?@==English][]

[
    "English",
    "English"
]

length関数により、要素数を数える

length([].language[?@==English][])

> 2

なお、jpコマンドはデフォルトでsearch関数を利用するようになっている。
jp#43

年齢の平均

jp -f test.json 'avg([].age)’
> 34.25

年齢が一番高い人

jp -f test.json 'max_by([], &age)’
{
    "age": 52,
    "programming": {
        "language": [
            "C",
            "BASIC",
            "NASM",
            "HTML",
            "Go",
            "Haskell"
        ]
    },
    "name": "Jem Tomas",
    "language": [
        "English",
        "French"
    ]
}

それ以外にも関数はあるけど、書いてて時間が足りないので
必要になったら使ってみよう

jmespathで利用できる関数一覧

29
34
0

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
29
34

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?