Correctly selecting keys and values in dictionary from parsed JSON in Python, using requests

I’m writing a twitch chat bot in python with TwtichIO, then i decided to add some pokemon functionality after i found out there’s a pokemon databse with a nice API and ended up using PokePy wrapper for PokeAPI. I have been hard-coding all my lookups(not sure that’s the correct word) Like this for example:

@bot.command(name="type", aliases=['t'])
async def types2(ctx, *, msg):
    pokemon = pokepy.V2Client().get_pokemon(msg.lower())
    pokemon_type = ""
    for x in range(len(pokemon[0].types)):
        pokemon_type += pokemon[0].types[x].type.name
        pokemon_type += " "
    await ctx.channel.send(str(pokemon_type))

But when i got to finding out pokemon’s weaknesses based on types, i found myself 3 layers deep into nested for loops and ifs, and knew i had to do more, just because i was hard-coding it. So i decided to try and find out how i can fetch the JSON file and parse it to a dict for easier access. I found out about the requests library. I think i have successfully used it but cannot manage to select the keys as needed. (i have used pprint() here to make reading easier) I will post like the first bit of the printed content because it’s too long. (Full output is here: https://pastebin.com/tkYKRcqY)

@bot.command(name="weak", aliases=['t'])
async def weakness(ctx, *, msg):
    deals = {'4x': [], '2x': [], '1x': [], '0.5x': [], '0.25x': [], '0x': []}
    response = requests.get('https://pokeapi.co/api/v2/type/fire')
    pprint(response)
    fetch = response.json()
    pprint(fetch)
    # test = fetch[damage_relations][double_damage_from]

Output:

{'damage_relations': {'double_damage_from': [{'name': 'ground',
                                              'url': 'https://pokeapi.co/api/v2/type/5/'},
                                             {'name': 'rock',
                                              'url': 'https://pokeapi.co/api/v2/type/6/'},
                                             {'name': 'water',
                                              'url': 'https://pokeapi.co/api/v2/type/11/'}],

So essentially what i want is, to grab only the names from damage_relations-> double_damage_from -> and store each name as 2x in my dict. Same for damage_relations -> half_damage_from -> name etc…. The idea is to return to chat what is the pokemon weak to, which will be the information stored in the dict. (There is also about 95% of the data that this fetches that i do not need for this)

I have also tried using json.loads(fetch) as i was desperate, but it returned an error saying it doesn’t expect dict as argument. Essentially my end goal is to put the correct damage values in the correct keys that i’ve created in the deals dictionary. Also there are some pokemon with multiple types, so for example if a pokemon has fire, ground as types i want to see if both of them will put the same type in the 2x key in deal dictionary, if they attempt to do so, i need to take out that type from 2x and place it in the 4x key.

I’m working blindly here, and it’s possible that the answer is very simple, i honestly do not understand it and am trying to bruteforce my way though, since i really do not understand what’s going wrong. If there is anything else that i need to provide as information please let me know.

Answer

  1. Let’s clean up type2. Note that it still has a space at the very end. Either manually remove it or look into str.join.

    @bot.command(name="type", aliases=['t'])
    async def types2(ctx, *, msg):
        pokemon = pokepy.V2Client().get_pokemon(msg.lower())
        pokemon_type = ""
        for p_type in pokemon[0].types:
            pokemon_type += f"{p_type.name} "
        await ctx.channel.send(pokemon_type) # already a string
    
  2. Just stick with fetch. It’s already the dict you want. You could use json.loads(response.text), but that’s redundant.

  3. Also there are some pokemon with multiple types, so for example if a pokemon has fire, ground as types i want to see if both of them will put the same type in the 2x key in deal dictionary, if they attempt to do so, i need to take out that type from 2x and place it in the 4x key.

I suggest storing a pokemon’s type(s) as a list (e.g. [fire], [fire, flying]). Let’s say a pokemon’s types are flying and rock. It’d have a 2x weakness and a 1/2 resistance against electric attacks. All you need to do is 2 * 1/2 == 1. If the attacking type is not present in the dict, just represent it as 1 (for no type shenanigans). To set the default, I suggest using dict.get.