Json.loads only returns names but not the values

Hi everyone
Tho I have lots of programming experience, I’m new to python and, of course, spyder. I have been following some youtube tutorial videos and now am trying out some api calls. I’m using Spyder 5.5.1

Here’s the code:

import requests
import json
response = requests.get("https://jsonplaceholder.typicode.com/todos/1")
print(response.status_code)
print(response.text)
res = json.loads(response.text)
for data in res:
    print(data)

Here’s the output:

200 ← status code is good

Next is the output of the full json file and that looks good too:

{
“userId”: 1,
“id”: 1,
“title”: “delectus aut autem”,
“completed”: false
}

Here’s the problem – it’s showing the name but not the value from the file. How come?:

userId
id
title
completed

Thanks!

The for data in res iterates over the keys in the dictionary res. To get the values, you would need to ask res using data, as in

for data in res:
    print(f'{data} : {res[data]}')

A better option would be to do

for key, value in res.items():
    print(f'{key=}, {value=}')

… if you are sure that the response is going to be key-value pairs, and not a list.

1 Like

See also

This is nothing to do with JSON. It’s how dicts work in Python.

See:

(@bschubert 's link is the usual recommendation, but it’s phrased in terms of understanding how the code is understood by Python; I tried to find one that’s focused on understanding how to write the code.)

1 Like

Thanks. I’ll check that out. However, all I’m doing is copying code that was presented in the python tutorial here: https://www.youtube.com/watch?v=WNvxR8RFzBg starting at minute 17:10. So I’m not sure why that would be different. Why would it work in the tutorial and not work for my python code? Could we be using different versions? I am finding some discrepancies. I found a problem in that tutorial when discussing sql too. I fixed the problem myself but only because I have lots of sql experience. I would wonder what people who don’t would make of the code not working for them.

Thanks!
Clem

In the video the API is returning a list-of-dicts, so iterating over that yields each element of the list, i.e. each one is itself a different dict. Your API is just returning a single dict, and iterating over that yields the keys of the dict (Python has been the same in this regard for decades). Your code will have to accommodate for this different return type.

2 Likes

Thanks @franklinvp – that worked! However, I don’t understand the syntax. Would you mind explaining it, please?

thanks
Clem

Which part do you not understand, the iterating over a dictionary, or the printing?

It, for example, res = {1: 111, 2: 222, 3: 333}, then res.items() returns an object that allows to look at the content of the dictionary res as (key, value) pairs, the tuples (1, 111), (2, 222), (3, 333). In particular, it provides a way to iterate over those tuples.

The for ... in asks to iterate over the tuples. Each tuple that comes out is assigned to what is in place of the .... Since we have for key, value in, then key, value gets assigned the value of each tuple. For example, in the first iteration of the loop it is the same as key, value = (1, 111).

key, value creates a tuple (key, value). So, it is as if we had (key, value) = (1, 111).

As a consequence, we get key = 1, and value = 111, in the first loop.

Mostly the printing. After doing some experimenting, I got how that works. The printing using that ‘f’ is interesting. I’ll dive into the documentation on that. Thanks.

Thanks! I have been doing some experimenting. I didn’t realize you could do a ‘for x,y in’ and it would collect the key, value pair. That makes sense now. But you’d think there’d be a json call that would do that already. Maybe there is. There’s still more to learn. Appreciate the help!!

clem

When you call res = json.loads(text), text, being in json format, is converted to a dictionary, a python data structure. At this point you’re not working with json anymore but in pure python, so there cannot be a json call to print (or do anything to) res.

Fyi, if all you want is to print the content of res, you can just print(res). The for key, value in res.item() is to iterate res and do anything with it. It’s more powerful, more flexible, but arguably overkill if you just want to see what’s inside.

I guess by “a json call” you mean “a function in the json module”; and I guess “that” refers to “collect[ing] the key, value pair”. But this still doesn’t make sense. The data is already as “collected” as it gets. The point of using the json library is that the raw text input is transformed into a Python data structure (a list or dict that may contain more lists/dicts, etc. arranged in a tree structure). Once you have that data, it’s just ordinary lists and dicts; they have no memory of how they were created, and working with them is done the same way as if you had obtained the data by any other means.

The purpose of a loop like this is to take apart the collected data, so that (in this case) each piece can be given to print separately. It wouldn’t be the responsibility of the json library to give you any code for this, first because it’s not a task specific to JSON, and second because there are arbitrarily many things you might want to do with the data. Looping over the .items of the dict gives you key/value pairs; the key, value in part of the loop syntax unpacks each pair into separate variables. That’s all standard Python stuff, and what you do from there (in the body of the loop) is up to you.

If you just want to see the entire chunk of data, you can print(res). That’s because dicts already know how to make a string representation of themselves. That again has nothing to do with JSON. But in this case you don’t have any control over the formatting; it’s up to the dict’s own logic. You may also be interested in the pprint standard library module; I’ll let you research that yourself.

The f'...' syntax isn’t part of print(), it’s part of string
literals - you’re looking for “format strings” or “f-strings”.

print() itself is pretty simple: it writes str(obj) to the output
for each argument obj, with a space separating each item and a newline
at the end. There are a few optional parameters for changing the
separator (normally a space) and the output file (normally the standard
output, sys.stdout), etc.

str() of a string is just the string itself. str() or another object
depends on the object.

1 Like