web-dev-qa-db-ja.com

プロパティでオブジェクトをフィルタリングし、jmespathのキーで選択します

サブプロパティの値に基づいて jmespath のオブジェクトのプロパティをフィルタリングしようとしています。サブプロパティが特定の値に設定されているプロパティのみを含めたいです。

このサンプルデータに基づく:

{
  "a": {
    "feature": {
      "enabled": true,
    }
  },
  "b": {
  },
  "c": {
    "feature": {
      "enabled": false
     }
  }
}

機能が有効になっているすべてのプロパティを持つオブジェクトを取得したいのですが。

{
  "a": {
    "feature": {
      "enabled": true,
    }
  }
}

このjmespathクエリを使用して、property. enabledはtrueに設定されています。残念ながら、動作しないようで、代わりに空の配列を返します。

*[?feature.enabled==`true`]

*.feature.enabledまたは*[feature.enabled]コンテキストなしでブール値のみを返します。

たとえ *[?feature.enabled==true]は機能します。これはプロパティ値の配列ですが、キー(aおよびc)も必要です。これをjmespathで実現する方法はありますか?

これはすべてansibleプレイブックの一部であるため、別の方法(Jinja2テンプレートまたはカスタムプラグイン)で選択を行う方法は確かにありますが、jmespathを試してみたかったので、そのようなタスクを実行できるはずです。

16

申し訳ありませんが、これはネイティブのJMESPathでは不可能です。
jqto_entriesのようなさまざまなツールには、この目的のためのカスタム組み込み関数があります。
jmespath.pyの場合、つまりAnsibleの場合、キー操作を実装するために pull request がハングします。

更新:json_query フィルターのパッチバージョンを作成しました。
詳細については、 this 回答を参照してください。

8

dict2items Ansible 2.5以降のフィルターでは、次のように実行できます。

- debug:
    msg: "{{ dict(my_data | dict2items | json_query('[?value.feature.enabled].[key, value]')) }}"

結果:

"msg": {
    "a": {
        "feature": {
            "enabled": true
        }
    }
}
7
techraf

短い答え(TL; DR)

  • 実際、そうです、これはネイティブのjmespathで可能です。
  • 問題は、ソースデータセットがこの種の汎用jmespathクエリに対して正規化されていないため、ソースデータセットに対するクエリが非常に煩雑になることです。

OPのソースデータに対する次の(長すぎる)jmespathクエリ...

[
  {
      "item_key":           `a`
      ,"feature_enabled":   @.a.feature.enabled
      ,source_object:       @.a
  }
  ,{
      "item_key":           `b`
      ,"feature_enabled":   @.b.feature.enabled
      ,source_object:       @.b
  }
  ,{
      "item_key":           `c`
      ,"feature_enabled":   @.c.feature.enabled
      ,source_object:       @.c
  }
]|[? feature_enabled == `true`]

...次の結果を生成します

[
  {
    "item_key": "a",
    "feature_enabled": true,
    "source_object": {
      "feature": {
        "enabled": true
      }
    }
  }
]

これは目的の出力と同じまたはほぼ同じですが、そこに到達するために脳を曲げる必要があったという事実は、正方形のペグを丸い穴に通そうとしていることを示しています。

落とし穴

このjmespathクエリが長くて扱いにくいように見える理由は、ソースデータセット自体が、汎用のjmespathクエリに対して不十分に正規化されているためです。

これは、sequentially-indexed-listで十分な場合に、最上位の照合方法としてobject keysを使用するためです。

任意の数の値を含む可能性のあるデータセットがある場合は常に、オブジェクトキーの代わりにトップレベルの照合にシーケンスを使用することをお勧めします。

Jmespathで何かを実行できることがわかったが、「任意の(固定されていない)長さのエントリのセット」に別の「エントリ」を追加するたびにjmespathクエリを変更する必要がある場合、Jmespathを操作するのではなく、Jmespathと戦っています。 。

Jmespathで「実行不可能」と思われるクエリが表示される場合は、ほとんどの場合、シーケンスの方が適している可能性のあるオブジェクトを使用しているデータ構造を処理しています。

オブジェクトキーは通常、固定数のプロパティを意味し、jmespathはそれをうまく処理できます。

順次列挙の代用として使用されていない限り、任意の深い入れ子のオブジェクトプロパティでも問題ありません。

オブジェクトのオブジェクトを回避するためにオブジェクトのシーケンスを作成しなければならない場合にのみ、物事は不快になり始めます... jmespathで完全に実行可能ですが、それは苦痛になるでしょう。

こちらもご覧ください

3
dreftymac