skip to Main Content

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?

2

Answers


  1. 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)
    
    Login or Signup to reply.
  2. 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)
    >>>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search