Andy
Andy

Reputation: 11

Why does Python first tell me my object is a dictionary (which it is), and then a list?

I am trying to access a dictionary, which has very long keys, and pull out some data from the keys. I am trying to look at the data, so while:

for k,v in line.items():
    if k == 'n':
        print('Label: ' + , v)
    if k == 'o':
        print(json_data.keys())

I want to use this to help me determine the length of the keys so that I could indice the dictionary. When I do this though, Python tells me

Traceback (most recent call last):
  File "C:\Users\spect\Desktop\gw2api\jsonapi.py", line 22, in <module>
    print(json_data.keys())
AttributeError: 'list' object has no attribute 'keys'

But what really befuddles me is that when I instead try to strip() or split() the dictionary, thinking I was confused and it was a string ---it's information from an API --- Python tells me

Traceback (most recent call last):
   File "C:\Users\spect\Desktop\gw2api\jsonapi.py", line 16, in <module>
     line.split()
AttributeError: 'dict' object has no attribute 'split'

The API is JSON and all the information is a dictionary in Python of multiple dictionary like items, so when Python makes it's dictionary it assigns some very long keys.

To answer your question I'm just practicing Python, working with a game API. #the usual import tools import urllib.parse import requests from pprint import pprint

#game api address schema
main_api = 'https://api.guildwars2.com/v2/titles?'
url = main_api + urllib.parse.urlencode({'ids':'all'})

json_data = requests.get(url).json()

#I resolved to switch around my two blocks of code so that the portions I n eeded were accessible. it was scoping more or less.
for line in json_data:
    for k,v in line.items():
        if k == 'achievements':
            json_data2 = requests.get(url).json()
            #here i'm supposed to be grabbing the id from json_data in a     placeholder fashion but really using the number to get the id f rom json_data2, it isn't working. json_data data is coming back.
            iden = v
            sec_url = 'https://api.guildwars2.com/v2/achievements?ids='
            url = sec_url + urllib.parse.urlencode({'ids':'iden'})
            json_data2 = requests.get(url).json()
            print('Achievement: ', iden)
        if k == 'name':
            print('Title: ', v)

hopefully that makes it clearer. The API sends back multiple dictionaries which python puts in a list.

Upvotes: 0

Views: 60

Answers (1)

Honza Z&#237;ka
Honza Z&#237;ka

Reputation: 483

You are using 2 variables: json_data which is a list, and line, which is a dict.

Based on your edit:

The API does NOT return multiple dictionaries, it returns a JSON in this form:

[
  {
    "id": 1,
    "name": "Traveler",
    "achievement": 111,
    "achievements": [
      111
    ]
  },
  {
    "id": 2,
    "name": "Guild Warrior",
    "achievement": 112,
    "achievements": [
      112
    ]
  },
...
]

To iterate over the response, you only need to parse it to json (by calling json.loads(), which I guess is exactly what json() method of requests.get() does). Then you can use a simple for loop:

for title in json_data:
    print("Title: " + title["name"])
    print("Achievement: " + title["achievement"])

Upvotes: 1

Related Questions