Jaka jest różnica między funkcjami json.load () i json.loads ()

172

W Pythonie, jaka jest różnica między json.load()i json.loads()?

Myślę, że obciążenie () funkcja musi być używany z obiektu pliku (Muszę zatem, aby użyć menedżera kontekstowe), natomiast () ładuje funkcyjne wziąć ścieżkę do pliku jako ciąg znaków. To trochę zagmatwane.

Czy litera „ sjson.loads()oznacza ciąg ?

Wielkie dzięki za odpowiedzi!

MMF
źródło
1
json.loads(s, *)- Cofnięcie s(a str, byteslub bytearrayprzykład zawierającego dokument JSON) - docs.python.org/3.6/library/json.html
deceze

Odpowiedzi:

160

Tak, soznacza string. json.loadsFunkcja nie bierze ścieżkę pliku, ale zawartość pliku jako ciąg. Zajrzyj do dokumentacji na https://docs.python.org/2/library/json.html !

Gijs
źródło
5
Powiązany artykuł wskazuje na niewłaściwą wersję Pythona. Pytanie jest oznaczone jako 2.7.
RvdK
odpowiedź od @Sufiyan Ghori zawiera ładne przykłady oprócz tej krótkiej, ale rzeczowej odpowiedzi.
Wład
65

Dodam tylko prosty przykład do tego, co wszyscy wyjaśnili,

json.load ()

json.loadmoże sam deserializować plik, tzn. akceptuje fileobiekt, na przykład

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

wyjdzie,

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

Jeśli json.loadszamiast tego użyję do otwarcia pliku,

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

Otrzymałbym ten błąd:

TypeError: oczekiwany ciąg lub bufor

json.loads ()

json.loads() ciąg deserializacji.

Żeby więc skorzystać json.loadsbędę musiał przekazać zawartość pliku za pomocą read()funkcji np.

korzystanie content.read()ze json.loads()zwrotem zawartości pliku,

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

Wynik,

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

Dzieje się tak, ponieważ typ content.read()to string, tj<type 'str'>

Jeśli używam json.load()z content.read(), otrzymam błąd,

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

Daje,

AttributeError: obiekt „str” nie ma atrybutu „odczyt”

Więc teraz znasz json.loadplik json.loadsdeserialze i deserializujesz ciąg.

Inny przykład,

sys.stdinzwraca fileobiekt, więc jeśli to zrobię print(json.load(sys.stdin)), otrzymam aktualne dane json,

cat json_data.json | ./test.py

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

Jeśli chcę użyć json.loads(), zrobiłbym to print(json.loads(sys.stdin.read()))zamiast tego.

Sufiyan Ghori
źródło
4
NAJLEPSZA (szczegółowa) odpowiedź. Powinien zostać poddany głosowaniu pozytywnemu, aby dołączyć do (krótkiej) zaakceptowanej odpowiedzi. Razem są mocni :-)
Wład
Do Twojej wiadomości, z Pythonem 3.6.5 with open()i json.loads()zwraca wyjątek:TypeError: the JSON object must be str, bytes or bytearray, not 'TextIOWrapper'
Sergiy Kolodyazhnyy
30

Dokumentacja jest dość przejrzysta: 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 () - obsługujący obiekt podobny do pliku zawierający dokument JSON) do obiektu Pythona przy użyciu tej tabeli konwersji.

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

Deserializuj s (instancję str lub Unicode zawierającą dokument JSON) do obiektu Python przy użyciu tej tabeli konwersji.

Tak loadjest w przypadku pliku, loadsastring

RvdK
źródło
1
„Obiekt podobny do pliku” a „instancja str / unicode”. Nie rozumiem, co nie jest jasne?
RvdK
7

SZYBKA ODPOWIEDŹ (bardzo uproszczona!)

json.load () pobiera PLIK

json.load () oczekuje pliku (obiektu pliku) - np. pliku, który otworzyłeś wcześniej, podanego przez ścieżkę pliku, na przykład 'files/example.json'.


json.loads () przyjmuje STRING

json.loads () oczekuje (prawidłowego) ciągu JSON - tj {"foo": "bar"}


PRZYKŁADY

Zakładając, że masz plik example.json z taką zawartością: {"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'
Wład
źródło
Samouczek o json.dump/ dumps& json.load/ loads bogotobogo.com/python/ ...
Wład
1

Metoda json.load () (bez „s” w „load”) może bezpośrednio odczytać plik:

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

json.loads () , która jest używana tylko dla argumentów łańcuchowych .

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'>

Tutaj widzimy, że po użyciu load () przyjmuje ciąg znaków (type (str)) jako słownik wejściowy i zwrotny .

Aditya patil
źródło
0

W pythonie3.7.7 definicja json.load jest następująca, zgodnie z kodem źródłowym 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 faktycznie wywołuje json.loads i używa go fp.read()jako pierwszego argumentu.

Więc jeśli twój kod to:

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

Robi się to tak samo:

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

Ale jeśli chcesz określić bajty odczytywane z pliku jako podobne fp.read(10)lub ciąg / bajty, które chcesz deserializować, nie pochodzą z pliku, powinieneś użyć json.loads ()

Jeśli chodzi o json.loads (), nie tylko deserializuje ciąg, ale także bajty. Jeśli sto bajty lub bytearray, zostanie najpierw zdekodowany na łańcuch. Możesz go również znaleźć w kodzie źródłowym.

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
źródło