Mukund Jalan
Mukund Jalan

Reputation: 1339

Extraction of values from json in python based on conditions

I am working with Python for the 1st time and wondering what would be the best way to do access fields in json strings.

I have a use case of extracting fields from array inside array kind of structure. I am able to get the value out of it using multiple fors & ifs using the dict's general ideology, but I assume there could be better ways provided by Python or Python's JSON library itself to do the same (something similar to the jq bash library's select), hence the question.

Below is the sample of my input and output

Code & Input

import json


def get_auth_ref(auth_policy_json: str) -> str:
    auth_policy_json_obj = json.loads(auth_policy_json)
    auth_policy_rules = auth_policy_json_obj["spec"]["rules"]
    for rule in auth_policy_rules:
        if "when" in rule:
            conditions = rule["when"]
            for condition in conditions:
                if condition["key"] == "request.headers[x-api-key]":
                    return condition["values"][0]


# some JSON:
auth_policy_json = '''{
  "apiVersion": "security.istio.io/v1beta1",
  "kind": "AuthorizationPolicy",
  "metadata": {
    "name": "some-policy",
    "namespace": "some-namespace"
  },
  "spec": {
    "action": "ALLOW",
    "rules": [
      {
        "to": [
          {
            "operation": {
              "methods": [
                "GET"
              ],
              "paths": [
                "/docs",
                "/openapi.json",
                "/redoc"
              ]
            }
          }
        ]
      },
      {
        "to": [
          {
            "operation": {
              "methods": [
                "GET"
              ],
              "paths": [
                "/healthz*",
                "/metrics*"
              ]
            }
          }
        ],
        "when": [
          {
            "key": "request.headers[User-Agent]",
            "values": [
              "Knative-Activator-Probe",
              "Go-http-client/1.1"
            ]
          }
        ]
      },
      {
        "when": [
          {
            "key": "request.headers[x-api-key]",
            "values": [
              "sample-api-key"
            ]
          }
        ]
      }
    ],
    "selector": {
      "matchLabels": {
        "serving.knative.dev/service": "some-service"
      }
    }
  }
}'''

print(get_auth_ref(auth_policy_json))

Output

sample-api-key

Upvotes: 0

Views: 389

Answers (1)

quasi-human
quasi-human

Reputation: 1928

jsonpath-ng can parse even such a nested json object very easily. It can be installed by the following command:

pip install --upgrade jsonpath-ng

Code:

import json
from jsonpath_ng.ext import parse

# Load the sample as dict
data = json.loads(auth_policy_json)

# Define an expression of a json path and search the target value
expr = parse(r'$..*[?key="request.headers[x-api-key]"]')
api_key = expr.find(data)[0].value['values'][0]
print(api_key)

# Define an expression of a more specific json path and search the target value
expr = parse(r'$.spec.rules.[*].when[?key="request.headers[x-api-key]"]')
api_key = expr.find(data)[0].value['values'][0]
print(api_key)

Output:

sample-api-key
sample-api-key

Upvotes: 1

Related Questions