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)