Яка різниця між функціями json.load () та json.loads ()


173

У Python в чому різниця між json.load()і json.loads()?

Я припускаю , що навантаження () функція повинна бути використана з файлом об'єктом (мені потрібно таким чином , щоб використовувати менеджер контексту) в той час як навантаження () функція на шляху до файлу у вигляді рядка. Це трохи заплутано.

Чи відповідає буква " s " json.loads()для рядка ?

Дякую за відповіді!


1
json.loads(s, *)- Deserialize sstr, bytesабо bytearrayпримірник , що містить JSON документ) - docs.python.org/3.6/library/json.html
deceze

Відповіді:


160

Так, sозначає строку. json.loadsФункція не приймає шлях до файлу, але вміст файлу у вигляді рядка. Подивіться документацію на https://docs.python.org/2/library/json.html !


5
Пов'язана стаття вказує на неправильну версію пітона. Питання позначено як 2.7.
RvdK

відповідь від @Sufiyan Ghori наводить приємні приклади на додаток до цієї короткої, але точної відповіді.
Wlad

65

Просто додамо простий приклад до того, що всі пояснили,

json.load ()

json.loadможе деріаріалізувати сам файл, тобто він приймає fileоб'єкт, наприклад,

# 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))

вийде,

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

Якщо я json.loadsзамість цього відкрию файл,

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

Я отримаю цю помилку:

TypeError: очікуваний рядок або буфер

json.loads ()

json.loads() деріаріалізувати рядок.

Тому для використання json.loadsмені доведеться передати вміст файлу за допомогою read()функції, наприклад,

використання content.read()із json.loads()поверненням вмісту файлу,

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

Вихід,

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

Це тому, що тип content.read()рядка, тобто<type 'str'>

Якщо я використовую json.load()з content.read(), я отримую помилку,

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

Дає,

AttributeError: "str" ​​об'єкт не має атрибута "read"

Отже, тепер ви знаєте json.loadфайл json.loadsdeserialze і деріаріалізуйте рядок.

Інший приклад,

sys.stdinповернути fileоб’єкт, тож якщо я це зробити print(json.load(sys.stdin)), я отримаю фактичні дані json,

cat json_data.json | ./test.py

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

Якщо я хочу використовувати json.loads(), я б зробив print(json.loads(sys.stdin.read()))замість цього.


4
НАЙКРАЩА (детальна) відповідь. Повинно бути додано до голосової супроводу (короткої) прийнятої відповіді. Разом вони сильні :-)
Wlad

Просто FYI, з Python 3.6.5 with open()і json.loads()повертає виняток:TypeError: the JSON object must be str, bytes or bytearray, not 'TextIOWrapper'
Сергій Колодяжний

31

Документація досить чітка: 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]]]]]]]])

Десеріалізувати fp (a .read () - підтримує файл-об’єкт, що містить документ JSON) до об’єкта Python, використовуючи цю таблицю перетворення.

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

Десеріалізуйте s (екземпляр str або unicode, що містить документ JSON) до об'єкта Python, використовуючи цю таблицю перетворення.

Так loadі для файлу, loadsдляstring


1
"Файл як об'єкт" vs "екземпляр str / unicode". Я не розумію, що не зрозуміло?
RvdK

7

ШВИДКИЙ ВІДПОВІДЬ (дуже спрощено!)

json.load () приймає FILE

json.load () очікує файл (файл-об’єкт) - наприклад, файл, який ви відкрили раніше, заданий файловим шляхом 'files/example.json'.


json.loads () займає STRING

json.loads () очікує (дійсний) рядок JSON - тобто {"foo": "bar"}


ПРИКЛАДИ

Припустимо, у вас є файл example.json з таким вмістом: {"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'

Підручник про json.dump/ dumps& json.load/ loads bogotobogo.com/python/…
Wlad

1

Метод json.load () (без "s" в "load") може читати файл безпосередньо:

import json
with open('strings.json') as f:
    d = json.load(f)
    print(d)

метод json.loads () , який використовується лише для рядкових аргументів.

import json

person = '{"name": "Bob", "languages": ["English", "Fench"]}'
print(type(person))
# Output : <type 'str'>

person_dict = json.loads(person)
print( person_dict)
# Output: {'name': 'Bob', 'languages': ['English', 'Fench']}

print(type(person_dict))
# Output : <type 'dict'>

Тут ми можемо бачити, що після використання load () приймає рядок (тип (str)) як словник введення та повернення .


0

У python3.7.7 визначення json.load наведено нижче відповідно до вихідного коду cpython :

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 насправді викликає json.loads і використовує fp.read()як перший аргумент.

Тож якщо ваш код:

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

Так само зробити:

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

Але якщо вам потрібно вказати зчитування байтів з файлу як подібне, fp.read(10)або рядок / байти, які ви хочете десеріалізувати, не з файлу, слід використовувати json.loads ()

Що стосується json.loads (), то він не тільки деріаріалізує рядок, але й байти. Якщо sце байти або байт-масив, він спочатку буде декодований до рядка. Ви також можете знайти його у вихідному коді.

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')
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.