Home > Enterprise >  Python Iterate over nested list dictionaries
Python Iterate over nested list dictionaries

Time:12-30

I have the following json content, returned from a REST API Request and I'm trying to iterate over the content and want to print every : pair. I know I can simply use print(json.dumps(config, indent=4))

Yet, I want to figure out how to structure the nested loop to use to iterate over the keys. I assume a first I have a list of dictionaries, ie. iterate over the list and then iterate over each dictionary in the list and print the ; pair. However, there are lists in each dictionary also with dictionaries within those lists.

[
    {
      "name": "<name>",
      "snippets": [
        {
          "name": "show_processes",
          "label": "Show Processes",
          "sql": "SELECT * FROM system.runtime",
          "can": {}
        }
      ],
      "host": "<host-url>",
      "port": "<port>",
      "database": "<database>",
      "db_timezone": null,
      "query_timezone": null,
      "schema": "<schema>",
      "after_connect_statements": null,
      "dialect": {
        "supports_cost_estimate": false,
        "automatically_run_sql_runner_snippets": true,
        "connection_tests": [
          "connect",
          "kill",
          "database_timezone",
          "database_version",
          "tmp_db",
          "cdt",
          "tmp_db_views"
        ],
        "supports_inducer": false,
        "supports_multiple_databases": false,
        "supports_persistent_derived_tables": true,
        "has_ssl_support": true,
        "name": "mike",
        "label": "<db>",
        "supports_streaming": true
      },
      "dialect_name": "sql",
      "example": false,
      "managed": false,
      "username": "<username>",
      "uses_oauth": false,
      "tunnel_id": null,
      "can": {
        "index": true,
        "index_limited": true,
        "show": true
      }
    },
    {
      "name": "<name>",
      "snippets": [],
      "host": "<host_url>",
      "port": "<port>",
      "database": "<db>",
      "db_timezone": null,
      "query_timezone": null,
      "schema": null,
      "after_connect_statements": null,
      "dialect": {
        "supports_cost_estimate": false,
        "connection_tests": [
          "connect",
          "query"
        ],
        "supports_inducer": false,
        "supports_multiple_databases": false,
        "has_ssl_support": true,
        "name": "<name>",
        "label": "<dbName>"
      },
      "dialect_name": "<dbType>",
      "example": false,
      "managed": false,
      "username": "<username>",
      "tunnel_id": null,
      "can": {
        "index": true,
        "index_limited": true,
        "show": true
      }
    },
    {
      "name": "<name>",
      "snippets": [
        {
          "name": "show_processes",
          "label": "Show Processes",
          "sql": "SHOW PROCESSLIST",
          "can": {}
        }
      ],
      "host": "<host-url>",
      "port": "<port>",
      "database": "<db>",
      "db_timezone": null,
      "query_timezone": null,
      "schema": null,
      "after_connect_statements": null,
      "dialect": {
        "supports_cost_estimate": false,
        "automatically_run_sql_runner_snippets": true,
        "connection_tests": [
          "connect",
          "kill",
          "query",
          "database_timezone",
          "database_version",
          "tmp_db",
          "mysql_tmp_tables",
          "cdt",
          "tmp_db_views"
        ],
        "supports_inducer": false,
        "supports_multiple_databases": false,
        "has_ssl_support": true,
        "name": "<name>",
        "label": "dbName>",
        "supports_streaming": true,
      },
      "dialect_name": "<dbType>",
      "example": false,
      "managed": false,
      "username": "<username>",
      "tunnel_id": null,
      "can": {
        "index": true,
        "index_limited": true,
        "show": true
      }
    }
  ]

CodePudding user response:

You can iterate recursively like this

import json


def iterate_json(obj, depth=0, callback=None):
    if isinstance(obj, list):
        # Handle list case
        for idx, nested_obj in enumerate(obj):
            print("\t" * depth   f"List #{idx}:")
            iterate_json(nested_obj, depth   1, callback)

    elif isinstance(obj, dict):
        # Handle dict case
        print("\t" * depth   f"Dict:")
        for key, value in obj.items():
            print("\t" * depth   f"Key: {key}")
            iterate_json(value, depth   1, callback)

    else:
        # it str, bool or None
        print("\t" * depth   f"Value: {obj}")
        
        # Here you can call your callback function to process JSON 
        callback(obj)

Output

List #0:
        Dict:
        Key: name
                Value: <name>
        Key: snippets
                List #0:
                        Dict:
                        Key: name
                                Value: show_processes
                        Key: label
                                Value: Show Processes
                        Key: sql
                                Value: SELECT * FROM system.runtime
                        Key: can
                                Dict:

If you only want to print str-str pairs you can simplify it


def iterate_json(obj):
    if isinstance(obj, list):
        # Handle list case
        for idx, nested_obj in enumerate(obj):
            iterate_json(nested_obj)

    elif isinstance(obj, dict):
        # Handle dict case
        for key, value in obj.items():
            if isinstance(value, list) or isinstance(value, dict):
                iterate_json(value)
            else:
                print(f"{key}: {value}")

Output

name: <name>
name: show_processes
label: Show Processes
sql: SELECT * FROM system.runtime
host: <host-url>
port: <port>
database: <database>
db_timezone: None
query_timezone: None
schema: <schema>
after_connect_statements: None
supports_cost_estimate: False
automatically_run_sql_runner_snippets: True
supports_inducer: False

CodePudding user response:

You can get the pairs recursively

def get_pairs(d, pairs=[]):
    # if it is iterable, check pairs in each element
    if type(d) in [list, tuple, set]:
        for item in d:
            new_pairs = get_pairs(item, pairs)
            pairs.extend(new_pairs)
    
    # if it is a dict, check key values for pairs
    if isinstance(d, dict):
        for key, value in d.items():
            
            # if dict value is iterable, check pairs in each element
            if type(value) in [list, tuple, set]:
                for item in value:
                    new_pairs = get_pairs(item, pairs)
                    pairs.extend(new_pairs)
                    
            # if it is a dict, get its pairs
            elif isinstance(value, dict):
                get_pairs(value, pairs)
                
            # otherwise, simply add key value as a new pair
            else:
                pairs.append((key, value))

    return pairs

print(get_pairs(data, pairs=[]))

The output should look like:

[('name', '<name>'),
 ('name', 'show_processes'),
 ('label', 'Show Processes'),
 ('sql', 'SELECT * FROM system.runtime'),
 ('name', '<name>'),
 ('name', 'show_processes'),
 ('label', 'Show Processes'),
...
  • Related