300

In Python, what is the difference between json.load() and json.loads()?

I guess that the load() function must be used with a file object (I need thus to use a context manager) while the loads() function take the path to the file as a string. It is a bit confusing.

Does the letter "s" in json.loads() stand for string?

NoDataDumpNoContribution
  • 10,591
  • 9
  • 64
  • 104
MMF
  • 5,750
  • 3
  • 16
  • 20
  • 1
    *`json.loads(s, *)` - Deserialize `s` (a `str`, `bytes` or `bytearray` instance containing a JSON document)* - https://docs.python.org/3.6/library/json.html – deceze Sep 27 '16 at 08:26

6 Answers6

277

Yes, s stands for string. The json.loads function does not take the file path, but the file contents as a string. Look at the documentation.

Josh Correia
  • 3,807
  • 3
  • 33
  • 50
Gijs
  • 10,346
  • 5
  • 27
  • 38
134

Just going to add a simple example to what everyone has explained,

json.load()

json.load can deserialize a file itself i.e. it accepts a file object, for example,

# open a json file for reading and print content using json.load
with open("/xyz/json_data.json", "r") as content:
  print(json.load(content))

will output,

{u'event': {u'id': u'5206c7e2-da67-42da-9341-6ea403c632c7', u'name': u'Sufiyan Ghori'}}

If I use json.loads to open a file instead,

# you cannot use json.loads on file object
with open("json_data.json", "r") as content:
  print(json.loads(content))

I would get this error:

TypeError: expected string or buffer

json.loads()

json.loads() deserialize string.

So in order to use json.loads I will have to pass the content of the file using read() function, for example,

using content.read() with json.loads() return content of the file,

with open("json_data.json", "r") as content:
  print(json.loads(content.read()))

Output,

{u'event': {u'id': u'5206c7e2-da67-42da-9341-6ea403c632c7', u'name': u'Sufiyan Ghori'}}

That's because type of content.read() is string, i.e. <type 'str'>

If I use json.load() with content.read(), I will get error,

with open("json_data.json", "r") as content:
  print(json.load(content.read()))

Gives,

AttributeError: 'str' object has no attribute 'read'

So, now you know json.load deserialze file and json.loads deserialize a string.

Another example,

sys.stdin return file object, so if i do print(json.load(sys.stdin)), I will get actual json data,

cat json_data.json | ./test.py

{u'event': {u'id': u'5206c7e2-da67-42da-9341-6ea403c632c7', u'name': u'Sufiyan Ghori'}}

If I want to use json.loads(), I would do print(json.loads(sys.stdin.read())) instead.

Sufiyan Ghori
  • 18,164
  • 14
  • 82
  • 110
  • Just FYI, with Python 3.6.5 the `with open()` and `json.loads()` returns an exception: `TypeError: the JSON object must be str, bytes or bytearray, not 'TextIOWrapper'` – Sergiy Kolodyazhnyy Dec 28 '19 at 08:25
34

Documentation is quite clear: https://docs.python.org/2/library/json.html

json.load(fp[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]])

Deserialize fp (a .read()-supporting file-like object containing a JSON document) to a Python object using this conversion table.

json.loads(s[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]])

Deserialize s (a str or unicode instance containing a JSON document) to a Python object using this conversion table.

So load is for a file, loads for a string

RvdK
  • 19,580
  • 4
  • 64
  • 107
  • 1
    "File like object" vs "a str/unicode instance". I don't understand what's not clear? – RvdK Jan 29 '19 at 07:56
30

QUICK ANSWER (very simplified!)

json.load() takes a FILE

json.load() expects a file (file object) - e.g. a file you opened before given by filepath like 'files/example.json'.


json.loads() takes a STRING

json.loads() expects a (valid) JSON string - i.e. {"foo": "bar"}


EXAMPLES

Assuming you have a file example.json with this content: { "key_1": 1, "key_2": "foo", "Key_3": null }

>>> import json
>>> file = open("example.json")

>>> type(file)
<class '_io.TextIOWrapper'>

>>> file
<_io.TextIOWrapper name='example.json' mode='r' encoding='UTF-8'>

>>> json.load(file)
{'key_1': 1, 'key_2': 'foo', 'Key_3': None}

>>> json.loads(file)
Traceback (most recent call last):
  File "/usr/local/python/Versions/3.7/lib/python3.7/json/__init__.py", line 341, in loads
TypeError: the JSON object must be str, bytes or bytearray, not TextIOWrapper


>>> string = '{"foo": "bar"}'

>>> type(string)
<class 'str'>

>>> string
'{"foo": "bar"}'

>>> json.loads(string)
{'foo': 'bar'}

>>> json.load(string)
Traceback (most recent call last):
  File "/usr/local/python/Versions/3.7/lib/python3.7/json/__init__.py", line 293, in load
    return loads(fp.read(),
AttributeError: 'str' object has no attribute 'read'
Wlad
  • 2,866
  • 3
  • 28
  • 42
  • Tutorial about `json.dump`/`dumps` & `json.load`/`loads` https://www.bogotobogo.com/python/python-json-dumps-loads-file-read-write.php – Wlad Dec 10 '19 at 16:17
0

In python3.7.7, the definition of json.load is as below according to cpython source code:

def load(fp, *, cls=None, object_hook=None, parse_float=None,
        parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):

    return loads(fp.read(),
        cls=cls, object_hook=object_hook,
        parse_float=parse_float, parse_int=parse_int,
        parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)

json.load actually calls json.loads and use fp.read() as the first argument.

So if your code is:

with open (file) as fp:
    s = fp.read()
    json.loads(s)

It's the same to do this:

with open (file) as fp:
    json.load(fp)

But if you need to specify the bytes reading from the file as like fp.read(10) or the string/bytes you want to deserialize is not from file, you should use json.loads()

As for json.loads(), it not only deserialize string but also bytes. If s is bytes or bytearray, it will be decoded to string first. You can also find it in the source code.

def loads(s, *, encoding=None, cls=None, object_hook=None, parse_float=None,
        parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
    """Deserialize ``s`` (a ``str``, ``bytes`` or ``bytearray`` instance
    containing a JSON document) to a Python object.

    ...

    """
    if isinstance(s, str):
        if s.startswith('\ufeff'):
            raise JSONDecodeError("Unexpected UTF-8 BOM (decode using utf-8-sig)",
                                  s, 0)
    else:
        if not isinstance(s, (bytes, bytearray)):
            raise TypeError(f'the JSON object must be str, bytes or bytearray, '
                            f'not {s.__class__.__name__}')
        s = s.decode(detect_encoding(s), 'surrogatepass')

Wenyi Li
  • 47
  • 7
0

The difference is in the source of the JSON text

json.load() expects to get the text from a file-like object json.loads() expects to get its text from a string object

Assume you have a file (json.txt) with the following contents

[ {"name": "Fred", "age": 32}, {"name": "Bob", "age": 21 } ] 

Now study the following:

>>> import json 
>>> with open("json.txt") as f:
      j1 = json.load(f) 
>>> j1 
[{u'age': 32, u'name': u'Fred'}, {u'age': 21, u'name': u'Bob'}] 

Now using strings

>>> with open("json.txt") as f: 
  txt = f.read()  
>>> txt 
'[ { "name": "Fred", "age": 32}, {"name": "Bob", "age": 21 } ]\n\n' 
>>> json.loads(txt) 
[{u'age': 32, u'name': u'Fred'}, {u'age': 21, u'name': u'Bob'}] 

In the first part, we read the file directly using json.load(). In the section part, we first read the file’s contents into a string variable, then pass that variable to json.loads()

The same relationship holds for json.dump() and json.dumps()