Home > Blockchain >  Dynamic values within a JSON parameter using Python
Dynamic values within a JSON parameter using Python

Time:01-26

To be clear, I am practicing my Python skills using CoinMarketCaps API.

The below code works great:

import json

# 1 JSON string in list, works
info_1_response = ['{"status": {"timestamp": "2023-01-25T22:59:58.760Z", "error_code": 0, "error_message": null, "elapsed": 16, "credit_count": 1, "notice": null}, "data": {"BTC": {"id": 1, "name": "Bitcoin", "symbol": "BTC"}}}']

for response in info_1_response:
    info_1_dict = json.loads(response)
    #print(info_1_dict) #works
    data = info_1_dict['data']['BTC']
    print(f"only id = {data['id']}")

OUTPUT: only id = 1

However, if I have 2 responses in a list, how would I got about getting the ID for each symbol (BTC/ETH)? Code:

info_2_response = ['{"status": {"timestamp": "2023-01-25T22:59:58.760Z", "error_code": 0, "error_message": null, "elapsed": 16, "credit_count": 1, "notice": null}, "data": {"BTC": {"id": 1, "name": "Bitcoin", "symbol": "BTC"}}}', '{"status": {"timestamp": "2023-01-25T22:59:59.087Z", "error_code": 0, "error_message": null, "elapsed": 16, "credit_count": 1, "notice": null}, "data": {"ETH": {"id": 1027, "name": "Ethereum", "symbol": "ETH"}}}']
for response in info_2_response:
    info_2_dict = json.loads(response)
    #print(info_2_dict) #works
    print(info_2_dict['data']) #works

OUTPUT:

{'BTC': {'id': 1, 'name': 'Bitcoin', 'symbol': 'BTC'}}

{'ETH': {'id': 1027, 'name': 'Ethereum', 'symbol': 'ETH'}}

But what if I only wanted the ID? It seems as if I would need a dynamic parameter as so:

data = info_2_dict['data']['DYNAMIC PARAMETER-(BTC/ETH)']

print(f"only id = {data['id']}")

Desired Output: 1, 1027

is this possible?

CodePudding user response:

Just iterate another level:

>>> for response in info_2_response:
...     response = json.loads(response)
...     for coin, data in response['data'].items():
...         print(coin, data['id'])
...
BTC 1
ETH 1027

We can remove some boilerplate from the body of the loop by using map(json.loads, ...), and since you know there is only one item in the dict, you can get fancy and use iterable unpacking:

>>> for response in map(json.loads, info_2_response):
...     [(coin, data), *_] = response['data'].items()
...     print(coin, data['id'])
...
BTC 1
ETH 1027

And if you expect there to only be one, you might want an error thrown, so you can do:

>>> for response in map(json.loads, info_2_response):
...     [(coin, data)] = response['data'].items()
...     print(coin, data['id'])
...
BTC 1
ETH 1027

So note, in the top version, [(coin, data), *_] = response['data'].items() will not fail if there is more than one item in the dict, the rest of the items get assigned to a list called _, which we are ignoring. But that's just a conventional name for a "throwaway" variable.

However, the other version would fail:

>>> response
{'status': {'timestamp': '2023-01-25T22:59:59.087Z', 'error_code': 0, 'error_message': None, 'elapsed': 16, 'credit_count': 1, 'notice': None}, 'data': {'ETH': {'id': 1027, 'name': 'Ethereum', 'symbol': 'ETH'}}}
>>> response['data']['FOO'] = "FOO STUFF"
>>> [(coin, data)] = response['data'].items()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 1)
>>>

CodePudding user response:

As long as the data dictionary only has a single key, you can do something like this:

import json

info_2_response = [
    """{"status": {"timestamp": "2023-01-25T22:59:58.760Z", "error_code": 0, "error_message": null, "elapsed": 16, "credit_count": 1, "notice": null},
    "data": {"BTC": {"id": 1, "name": "Bitcoin", "symbol": "BTC"}}}""",
    """{"status": {"timestamp": "2023-01-25T22:59:59.087Z", "error_code": 0, "error_message": null, "elapsed": 16, "credit_count": 1, "notice": null},
    "data": {"ETH": {"id": 1027, "name": "Ethereum", "symbol": "ETH"}}}""",
]
for response in info_2_response:
    info_2_dict = json.loads(response)
    print(list(info_2_dict["data"].values())[0]["id"])

This will print:

1
1027

The code works by using the .values() method of a dictionary to get a list of values. Since there's only a single value, we just take the first item from the list and then look up the id attribute.

We can expand the compound statement to make the operations a little more clear:

for response in info_2_response:
    info_2_dict = json.loads(response)
    all_values = info_2_dict["data"].values()
    first_value = list(all_values)[0]
    id = first_value["id"]
    print(id)
  • Related