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'),
...