Разное

Json file python: JSON в Python — Примеры работы модуля JSON

Содержание

JSON в Python — Примеры работы модуля JSON

Сразу после появления, JSON быстро стал де факто стандартом обмена информации. Вероятно вы здесь из-за того, что вы хотите переместить данные из одного места в другое. Возможно вы получаете данные через API, или храните их в документной базе данных. Так или иначе, вы заинтересовались JSON, и вам нужно пользоваться им через Python.

Содержание

К счастью, это достаточно тривиальная задача, и как и с большинством тривиальных задач, Python делает все до омерзения простым.

Итак, используем ли мы JSON для хранения и обмена данными? Именно так. Это не более, чем стандартизированный формат, который используется сообществом для передачи данных. Помните, что JSON не является единственным доступным форматом для такой работы, XML и YAML наверное, единственные альтернативные способы, которые стоит упомянуть.

Подробнее про JSON

Не удивительно, что JavaScript Object Notation был вдохновен подмножеством языка программирования JavaScript, связанным с синтаксисом объектного литерала. У них есть отличный сайт, в котором все прекрасно объясняется. Не переживайте: JSON уже давно стал агностиком языка и существует как отдельный стандарт, по этому мы можем убрать JavaScript из этой дискуссии.

Есть вопросы по Python?

На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!

Telegram Чат & Канал

Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!

Паблик VK

Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!


В конечном счете, большая часть сообщества приняла JSON благодаря его простоте как для людей, так и для машин.
Смотрите, это JSON!

Структура JSON

Готовьтесь. Я собираюсь показать реальный пример JSON— такой же, какой вы встретите в реальной жизни. Это нормально, подразумевается что JSON является читаемым для любого, кто пользовался С-языками, а Python – это С-язык, так что мы говорим о вас!

{
«firstName»: «Jane»,
«lastName»: «Doe»,
«hobbies»: [«running», «sky diving», «singing»],
«age»: 35,
«children»: [
{
«firstName»: «Alice»,
«age»: 6
},
{
«firstName»: «Bob»,
«age»: 8
}
]
}



{

    «firstName»: «Jane»,

    «lastName»: «Doe»,

    «hobbies»: [«running», «sky diving», «singing»],

    «age»: 35,

    «children»: [

        {

            «firstName»: «Alice»,

            «age»: 6

        },

        {

            «firstName»: «Bob»,

            «age»: 8

        }

    ]

}

Как видите, JSON поддерживает примитивные типы, такие как строки python и числа, а также вложенные списки и объекты.

Погодите, это выглядит как словарь Python, верно? На данный момент это достаточно универсальная нотация объектов, и не думаю что UON может так же легко отскакивать от зубов. Кстати, предлагайте альтернативы в комментариях!

НУ что же, вы пережили первый контакт с диким JSON. Теперь вам нужно научиться приручать его!

Python поддерживает JSON

Python содержит встроенный модуль под названием json для кодирования и декодирования данных JSON.

Просто импортируйте модуль в начале вашего файла:

Небольшой словарь

Как правило, процесс кодирования JSON называется сериализация. Этот термин обозначает трансформацию данных в серию байтов (следовательно, серийных) для хранения или передачи по сети. Также вы, возможно, уже слышали о термине «маршалинг», но это уже совсем другая область.

Естественно, десериализация — является противоположным процессом декодирования данных, которые хранятся или направлены в стандарт JSON.

Звучит как много технических терминов. Определенно. Но в реальности, все, о чем мы сейчас говорим — это чтение и написание. Представьте это следующим образом: кодирование это запись данных на диск, в то время как декодирование — это чтение данных в памяти.

Сериализация JSON

Что происходит после того, как компьютер обрабатывает большие объемы информации? Ему нужно принять дамп данных. Соответственно, модуль json предоставляет метод dump() для записи данных в файлы. Также есть метод dumps() для записей в строку Python.

Простые объекты Python переводятся в JSON согласно с весьма интуитивной конверсией.

PythonJSON
dictobject
list, tuplearray
strstring
int, long, floatnumber
Truetrue
Falsefalse
Nonenull

Пример сериализации JSON Python

Представьте, что вы работаете с объектом Python в памяти, который выглядит следующим образом:

data = {
«president»: {
«name»: «Zaphod Beeblebrox»,
«species»: «Betelgeusian»
}
}



data = {

    «president»: {

        «name»: «Zaphod Beeblebrox»,

        «species»: «Betelgeusian»

    }

}

Сохранить эту информацию на диск — критично, так что ваша задача — записать на файл.

Используя контекстный менеджер Python, вы можете создать файл под названием data_file.json и открыть его в режиме write (файлы JSON имеют расширение .json).

with open(«data_file.json», «w») as write_file:
json.dump(data, write_file)



with open(«data_file.json», «w») as write_file:

    json.dump(data, write_file)

Обратите внимание на то, что dump() принимает два позиционных аргумента: (1) объект данных, который сериализуется и (2), файловый объект, в который будут вписаны байты.

Или, если вы склонны продолжать использовать эти сериалзированные данные JSON в вашей программе, вы можете работать как со строкой.

json_string = json.dumps(data)



json_string = json.dumps(data)

Обратите внимание, что файловый объект является пустым, так как вы на самом деле не выполняете запись на диск. Кроме того, dumps() аналогичен dump().

Ура! У вас получился малыш JSON и вы можете выпустить его в реальный мир, чтобы он вырос большим и сильным.

Несколько полезных аргументов

Помните, что JSON создан таким образом, чтобы быть читаемым для людей. Но читаемого синтаксиса недостаточно, если все слеплено вместе. Кроме этого, ваш стиль программирования скорее всего отличается от моего, и вам будет проще читать код, если он отформатирован по вашему вкусу.

Обратите внимание: Методы dump() и dumps() пользуются одними и теми же аргументами ключевых слов.

Первая опция, которую большинство людей хотят поменять, это пробел. Вы можете использовать аргумент indent для определения размера отступа вложенных структур. Ощутите разницу лично, используя данные, упомянутые выше и выполните следующие команды в консоли:

json.dumps(data)
json.dumps(data, indent=4)



json.dumps(data)

json.dumps(data, indent=4)

Еще один вариант форматирования — это аргумент separators. По умолчанию, это двойной кортеж строк разделителя («, «, «: «), но обычно в качестве альтернативы для компактного JSON является («,», «:»). Взгляните на пример JSON еще раз, чтобы понять, где в игру вступают разделители.

Есть и другие аргументы, такие как sort_keys, но я не имею понятия, что он делает. Вы можете найти полный список в документации, если вам интересно.

Десериализация JSON

Отлично, похоже вам удалось поймать экземпляр дикого JSON! Теперь нам нужно предать ему форму. В модуле json вы найдете load() и loads() для превращения кодированных данных JSON в объекты Python.

Как и сериализация, есть простая таблица конверсии для десериализации, так что вы можете иметь представление о том, как все выглядит.

JSONPython
objectdict
arraylist
stringstr
number (int)int
number (real)float
trueTrue
falseFalse
nullNone

Технически, эта конверсия не является идеальной инверсией таблицы сериализации. По сути, это значит что если вы кодируете объект сейчас, а затем декодируете его в будущем, вы можете не получить тот же объект назад. Я представляю это как своего рода телепортацию: мои молекулы распадаются в точке А и собираются в точке Б. Буду ли я тем же самым человеком?

В реальности, это как попросить одного друга перевести что-нибудь на японский, а потом попросить другого друга перевести это обратно на русский. В любом случае, самым простым примером будет кодировать кортеж и получить назад список после декодирования, вот так:

blackjack_hand = (8, «Q»)
encoded_hand = json.dumps(blackjack_hand)
decoded_hand = json.loads(encoded_hand)

print(blackjack_hand == decoded_hand) # False

print(type(blackjack_hand)) # <class ‘tuple’>
print(type(decoded_hand)) # <class ‘list’>

print(blackjack_hand == tuple(decoded_hand)) # True



blackjack_hand = (8, «Q»)

encoded_hand = json.dumps(blackjack_hand)

decoded_hand = json.loads(encoded_hand)

 

print(blackjack_hand == decoded_hand) # False

 

print(type(blackjack_hand)) # <class ‘tuple’>

print(type(decoded_hand)) # <class ‘list’>

 

print(blackjack_hand == tuple(decoded_hand)) # True

Пример десериализации JSON Python

На этот раз, представьте что у вас есть некие данные, хранящиеся на диске, которыми вы хотите манипулировать в памяти. Вам все еще нужно будет воспользоваться контекстным менеджером, но на этот раз, вам нужно будет открыть существующий data_file.json в режиме для чтения.

with open(«data_file.json», «r») as read_file:
data = json.load(read_file)



with open(«data_file.json», «r») as read_file:

    data = json.load(read_file)

Здесь все достаточно прямолинейно, но помните, что результат этого метода может вернуть любые доступные типы данных из таблицы конверсий. Это важно только в том случае, если вы загружаете данные, которые вы ранее не видели. В большинстве случаев, корневым объектом будет dict или list.

Если вы внесли данные JSON из другой программы, или полученную каким-либо другим способом строку JSON форматированных данных в Python, вы можете легко десериализировать это при помощи loads(), который естественно загружается из строки:

json_string = «»»
{
«researcher»: {
«name»: «Ford Prefect»,
«species»: «Betelgeusian»,
«relatives»: [
{
«name»: «Zaphod Beeblebrox»,
«species»: «Betelgeusian»
}
]
}
}
«»»

data = json.loads(json_string)



json_string = «»»

{

    «researcher»: {

        «name»: «Ford Prefect»,

        «species»: «Betelgeusian»,

        «relatives»: [

            {

                «name»: «Zaphod Beeblebrox»,

                «species»: «Betelgeusian»

            }

        ]

    }

}

«»»

 

data = json.loads(json_string)

Ву а ля! Вам удалось укротить дикого JSON, теперь он под вашим контролем. Но что вы будете делать с этой силой — остается за вами. Вы можете кормить его, выращивать, и даже научить новым приемам. Не то чтобы я не доверяю вам, но держите его на привязи, хорошо?

Пример работы с JSON Python

Для тестового API, мы воспользуемся JSONPlaceholder, отличный источник фейковых данных JSON для практических целей.

Для начала, создайте файл под названием scratch.py, или как вам удобно. Здесь я не могу вас контролировать.

Вам нужно выполнить запрос API в сервис JSONPlaceholder, так что просто используйте пакет requests, чтобы он сделал за вас всю грязную работу. Добавьте следующие импорты вверху файла:

import json
import requests



import json

import requests

Теперь вам предстоит поработать со списком TODOs, потому что… это своего рода обряд посвящения, вроде того.

Идем дальше и создаем запрос в API JSONPlaceholder для конечной точки GET /todos. Если вы слабо знакомы с запросами, есть очень удобный метод json(), который выполнит за вас всю работу, но вы можете попрактиковаться в использовании модуля json для десериализации атрибута текста объекта response. Это должно выглядеть следующим образом:

response = requests.get(«https://jsonplaceholder.typicode.com/todos»)
todos = json.loads(response.text)



response = requests.get(«https://jsonplaceholder.typicode.com/todos»)

todos = json.loads(response.text)

Не верится, что это работает? Хорошо, запустите файл в интерактивном режиме и проверьте лично. Пока вы там, проверьте тип todos. Если вам любопытно, обратите внимание на первые 10 элементов в списке.

response = requests.get(«https://jsonplaceholder.typicode.com/todos»)
todos = json.loads(response.text)

print(todos == response.json()) # True
print(type(todos)) # <class ‘list’>

print(todos[:10]) # …



response = requests.get(«https://jsonplaceholder.typicode.com/todos»)

todos = json.loads(response.text)

 

print(todos == response.json()) # True

print(type(todos)) # <class ‘list’>

 

print(todos[:10]) # …

Как видите, никто вас не обманывает, и мы ценим здравый скептицизм.

Что такое интерактивный режим? Я уже думал вы не спросите! Вы знакомы с тем, что приходится постоянно прыгать туда-сюда между вашим редактором и терминалом? Мы, хитрые питонисты, используем интерактивный флаг -i, когда запускаем скрипт. Это отличный небольшой трюк для тестирования кода, так как он запускает скрипт, и затем открывает интерактивную командную строку с доступом ко всем данным скрипта!

Хорошо, теперь перейдем к действиям. Вы можете видеть структуру данных полученную от тестового API, посетив адрес в браузере https://jsonplaceholder.typicode.com/todos:

{
«userId»: 1,
«id»: 1,
«title»: «delectus aut autem»,
«completed»: false
}



{

    «userId»: 1,

    «id»: 1,

    «title»: «delectus aut autem»,

    «completed»: false

}

Здесь несколько пользователей, каждый из которых имеет уникальный userId, а каждая задача имеет свойство Boolean. Можете определить, какие пользователи выполнили большую часть задач?

response = requests.get(«https://jsonplaceholder.typicode.com/todos»)
todos = json.loads(response.text)

# Соотношение userId с числом выполненных пользователем задач.
todos_by_user = {}

# Увеличение выполненных задач каждым пользователем.
for todo in todos:
if todo[«completed»]:
try:
# Увеличение количества существующих пользователей.
todos_by_user[todo[«userId»]] += 1
except KeyError:
# Новый пользователь, ставим кол-во 1.
todos_by_user[todo[«userId»]] = 1

# Создание отсортированного списка пар (userId, num_complete).
top_users = sorted(todos_by_user.items(),
key=lambda x: x[1], reverse=True)

#Получение максимального количества выполненных задач.
max_complete = top_users[0][1]

# Создание списка всех пользователей, которые выполнили
# максимальное количество задач.
users = []
for user, num_complete in top_users:
if num_complete < max_complete:
break
users.append(str(user))

max_users = » and «.join(users)


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

response = requests.get(«https://jsonplaceholder.typicode.com/todos»)

todos = json.loads(response.text)

 

# Соотношение userId с числом выполненных пользователем задач.

todos_by_user = {}

 

# Увеличение выполненных задач каждым пользователем.

for todo in todos:

    if todo[«completed»]:

        try:

            # Увеличение количества существующих пользователей.

            todos_by_user[todo[«userId»]] += 1

        except KeyError:

            # Новый пользователь, ставим кол-во 1.

            todos_by_user[todo[«userId»]] = 1

 

# Создание отсортированного списка пар (userId, num_complete).

top_users = sorted(todos_by_user.items(),

                   key=lambda x: x[1], reverse=True)

 

#Получение максимального количества выполненных задач.

max_complete = top_users[0][1]

 

# Создание списка всех пользователей, которые выполнили

# максимальное количество задач.

users = []

for user, num_complete in top_users:

    if num_complete < max_complete:

        break

    users.append(str(user))

 

max_users = » and «.join(users)

Да, да, ваша версия лучше, но суть в том, что теперь вы можете манипулировать данными JSON как нормальным объектом Python!

Не знаю как вы, но я запустил скрипт в интерактивном режиме еще раз, и получил следующий результат:

s = «s» if len(users) > 1 else «»
print(f»user{s} {max_users} completed {max_complete} TODOs»)
# users 5 and 10 completed 12 TODOs



s = «s» if len(users) > 1 else «»

print(f»user{s} {max_users} completed {max_complete} TODOs»)

# users 5 and 10 completed 12 TODOs

Это круто, и все такое, но мы занимаемся изучением JSON. В качестве вашей последней задачи, вы создадите файл JSON, который содержит готовые задачи (TODO) для каждого пользователя, который выполнил максимальное количество задач. Здесь мы использовали F-Строки Python.

Все, что вам нужно сделать, это отфильтровать задачи и вписать итоговый список в файл. Ради оригинальности, вы можете назвать файл выдачи filtered_data_file.json. Существует много способов сделать это, вот один из них:

# Определить функцию для фильтра выполненных задач
# с пользователями с максимально выполненными задачами.
def keep(todo):
is_complete = todo[«completed»]
has_max_count = todo[«userId»] in users
return is_complete and has_max_count

# Записать отфильтрованные задачи в файл
with open(«filtered_data_file.json», «w») as data_file:
filtered_todos = list(filter(keep, todos))
json.dump(filtered_todos, data_file, indent=2)



# Определить функцию для фильтра выполненных задач

# с пользователями с максимально выполненными задачами.

def keep(todo):

    is_complete = todo[«completed»]

    has_max_count = todo[«userId»] in users

    return is_complete and has_max_count

 

# Записать отфильтрованные задачи в файл

with open(«filtered_data_file.json», «w») as data_file:

    filtered_todos = list(filter(keep, todos))

    json.dump(filtered_todos, data_file, indent=2)

Отлично, теперь вы избавились от всех данных, которые вам не нужны и сохранили необходимое для нового файла!

Запустите скрипт еще раз и проверьте filtered_data_file.json, чтобы убедиться в том, что все работает. Он будет в той же папке, что и scratch.py, когда вы запустите его.

Теперь, когда вы зашли так далеко, вы начинаете понимать что коснулись темы с большим потенциалом, не так ли? Не зазнавайтесь: скромность сестра таланта. Хотя и не могу не согласиться. Пока что мы работали в плавном потоке, но под конец мы можем поддать газку.

Кодирование и декодирование объектов Python

Что случается, когда мы пытаемся сериализировать класс Elf из приложения Dungeons & Dragons, с которым вы работаете?

class Elf:
def __init__(self, level, ability_scores=None):
self.level = level
self.ability_scores = {
«str»: 11, «dex»: 12, «con»: 10,
«int»: 16, «wis»: 14, «cha»: 13
} if ability_scores is None else ability_scores
self.hp = 10 + self.ability_scores[«con»]



class Elf:

    def __init__(self, level, ability_scores=None):

        self.level = level

        self.ability_scores = {

            «str»: 11, «dex»: 12, «con»: 10,

            «int»: 16, «wis»: 14, «cha»: 13

        } if ability_scores is None else ability_scores

        self.hp = 10 + self.ability_scores[«con»]

Ничего удивительного, Возникла ошибка, что класс Elf нельзя сериализировать:

elf = Elf(level=4)
json.dumps(elf)
TypeError: Object of type ‘Elf’ is not JSON serializable



elf = Elf(level=4)

json.dumps(elf)

TypeError: Object of type ‘Elf’ is not JSON serializable

Хотя, модуль json может обрабатывать большинство типов Python, он не понимает, как кодировать пользовательские типы данных по умолчанию. Это как пытаться поместить кубик в круглое отверстие — вам понадобится бензопила и надзор специалиста.

Упрощение структур данных

Сейчас вопрос в том, что делать с более сложными структурами данных. Например, вы можете попробовать кодировать и декодировать JSON вручную, но есть более разумное решение, которое избавит вас от лишней работы. Вместо того, чтобы идти непосредственно от пользовательского типа данных к JSON, вы можете перейти к промежуточному шагу.

Все что вам нужно, это отобразить ваши данные в контексте встроенных типов, которые изначально понятны json. По сути, вы переводите более сложный объект в его упрощенное представление, которое модуль json затем переводит в JSON.

Это наглядно представляется в математике: А = В, и В = С, значит А = С.

Чтобы добиться этого, вам нужен сложный объект для работы. Вы можете использовать любой пользовательский класс на ваш вкус, но Python имеет встроенный тип под названием complex, для представления сложных чисел, и он не может быть сериализированным по умолчанию. Итак, ради этих примеров, ваш сложный объект станет сложным объектом. Уже запутались?

z = 3 + 8j
print(type(z)) # <class ‘complex’>

json.dumps(z)
TypeError: Object of type ‘complex’ is not JSON serializable



z = 3 + 8j

print(type(z)) # <class ‘complex’>

 

json.dumps(z)

TypeError: Object of type ‘complex’ is not JSON serializable

Откуда приходят комплексные числа? Когда реальное число и представляемое число очень любят друг друга, они складываются вместе для создания числа, которое (справедливо) называется комплексным.

Хороший вопрос, который стоит задать себе при работе со сложными типами: «Какой минимальный объем информации необходим для воссоздания этого объекта?» В случае со комплексными числами, вам нужно знать только реальное и представляемое число, доступ к которым (в качестве атрибутов) доступен в объекте complex:

z = 3 + 8j

print(z.real) # 3.0
print(z.imag) # 8.0



z = 3 + 8j

 

print(z.real) # 3.0

print(z.imag) # 8.0

Передачи одних и тех же чисел в сложный конструктор достаточно для удовлетворения оператора сравнения __eq__:

z = 3 + 8j

print( complex(3, 8) == z ) # True



z = 3 + 8j

 

print( complex(3, 8) == z ) # True

Разбивать пользовательские типы данных на их составляющие компоненты — критически важно как для процесса сериализации, так и для десериализации.

Кодирование пользовательских типов

Для перевода пользовательского объекта в JSON, все что вам нужно — это предоставить функцию кодирования параметру по умолчанию метода dump(). Модуль json вызовет эту функцию для любых объектов, которые не являются естественно сериализируемыми. Вот простая функция декодирования, которую вы можете использовать на практике:

def encode_complex(z):
if isinstance(z, complex):
return (z.real, z.imag)
else:
type_name = z.__class__.__name__
raise TypeError(f»Object of type ‘{type_name}’ is not JSON serializable»)



def encode_complex(z):

    if isinstance(z, complex):

        return (z.real, z.imag)

    else:

        type_name = z.__class__.__name__

        raise TypeError(f»Object of type ‘{type_name}’ is not JSON serializable»)

Обратите внимание на то, что ожидается получение ошибки TypeError, если вы не получите ожидаемый тип объекта. Таким образом, вы избегаете случайной сериализации любых пользовательских типов. Теперь вы можете кодировать сложные объекты самостоятельно!

>>> json.dumps(9 + 5j, default=encode_complex)
‘[9.0, 5.0]’

>>> json.dumps(elf, default=encode_complex)
TypeError: Object of type ‘Elf’ is not JSON serializable



>>> json.dumps(9 + 5j, default=encode_complex)

‘[9.0, 5.0]’

 

>>> json.dumps(elf, default=encode_complex)

TypeError: Object of type ‘Elf’ is not JSON serializable

Почему мы кодируем комплексное число как кортеж? Хороший вопрос. Это определенно не является единственными выбором, впрочем, как и не является лучшим выбором. Фактически, это не может быть хорошим отображением, если вы планируете декодировать объект в будущем, что вы и увидите дальше.

Еще один частый подход — создать дочерний класс JSONEncoder и переопределить его метод default():

class ComplexEncoder(json.JSONEncoder):
def default(self, z):
if isinstance(z, complex):
return (z.real, z.imag)
else:
super().default(self, z)



class ComplexEncoder(json.JSONEncoder):

    def default(self, z):

        if isinstance(z, complex):

            return (z.real, z.imag)

        else:

            super().default(self, z)

Вместо создания ошибки TypeError, вы можете дать классу base справиться с ней. Вы можете использовать его как напрямую в метод dump() при помощи параметра cls, или создав экземпляр encoder-а и вызова метода encode():

>>> json.dumps(2 + 5j, cls=ComplexEncoder)
‘[2.0, 5.0]’

>>> encoder = ComplexEncoder()
>>> encoder.encode(3 + 6j)
‘[3.0, 6.0]’



>>> json.dumps(2 + 5j, cls=ComplexEncoder)

‘[2.0, 5.0]’

 

>>> encoder = ComplexEncoder()

>>> encoder.encode(3 + 6j)

‘[3.0, 6.0]’

Декодирование пользовательских типов

В то время, как реальные и представляемые части сложных чисел абсолютно необходимы, на самом деле их не совсем достаточно для воссоздания объекта. Вот что случается, если вы попробуете кодировать комплексное число при помощи ComplexEncoder, а затем декодировать результат:

>>> complex_json = json.dumps(4 + 17j, cls=ComplexEncoder)
>>> json.loads(complex_json)
[4.0, 17.0]



>>> complex_json = json.dumps(4 + 17j, cls=ComplexEncoder)

>>> json.loads(complex_json)

[4.0, 17.0]

Все что вы получаете обратно — это список, и вы можете передать значения в конструктор, если вы хотите получить этот сложный объект еще раз. Напоминаю о нашем разговоре о телепортации. Чего нам в итоге не хватает? Метаданные, или информации о типа данных, которые вы кодируете.

Я предполагаю, что вопрос, который действительно важно задать себе, это «Какое минимальное количество информации, которая необходима, и которой достаточно для воссоздания объекта?»

Модуль json ожидает, что все пользовательские типы будут отображаться как объекты стандарта JSON. Для разнообразия, вы можете создать файл JSON, на этот раз назовем его complex_data.json и добавим следующий объект, отображающий комплексное число:

{
«__complex__»: true,
«real»: 42,
«imag»: 36
}



{

    «__complex__»: true,

    «real»: 42,

    «imag»: 36

}

Заметили хитрую часть? Вот ключ «__complex__» является метаданными, которые мы только что упоминали. Неважно, какое ассоциируемое значение мы имеем. Чтобы эта хитрость сработала, все что вам нужно, это подтвердить существование ключа:

def decode_complex(dct):
if «__complex__» in dct:
return complex(dct[«real»], dct[«imag»])
return dct



def decode_complex(dct):

    if «__complex__» in dct:

        return complex(dct[«real»], dct[«imag»])

    return dct

Если «__complex__» не находится в словаре, вы можете просто вернуть объект и позволить декодеру по умолчанию разобраться с этим.

Каждый раз, когда метод load() пытается парсить объект, у вас есть возможность выступить в роли посредника, перед тем как декодер пройдет свой путь с данными. Вы можете сделать это, спарсив вашу функцию декодирования с параметром object_hook.

Теперь сыграем в ту же игру, что и раньше:

with open(«complex_data.json») as complex_data:
data = complex_data.read()
z = json.loads(data, object_hook=decode_complex)

print(type(z)) # <class ‘complex’>



with open(«complex_data.json») as complex_data:

    data = complex_data.read()

    z = json.loads(data, object_hook=decode_complex)

 

print(type(z)) # <class ‘complex’>

Хотя объект object_hook может показаться аналогом параметра по умолчанию метода dump(), на самом деле аналогия здесь же и заканчивается.

Это не просто работает с одним объектом. Попробуйте внести этот список сложных чисел в complex_data.json и запустить скрипт еще раз:

[
{
«__complex__»:true,
«real»:42,
«imag»:36
},
{
«__complex__»:true,
«real»:64,
«imag»:11
}
]



[

  {

    «__complex__»:true,

    «real»:42,

    «imag»:36

  },

  {

    «__complex__»:true,

    «real»:64,

    «imag»:11

  }

]

Если все идет гладко, вы получите список комплексных объектов:

with open(«complex_data.json») as complex_data:
data = complex_data.read()
numbers = json.loads(data, object_hook=decode_complex)


print(numbers) # [(42+36j), (64+11j)]



with open(«complex_data.json») as complex_data:

    data = complex_data.read()

    numbers = json.loads(data, object_hook=decode_complex)

 

 

print(numbers) # [(42+36j), (64+11j)]

Вы также можете попробовать создать подкласс JSONDecoder и переопределить object_hook, но лучше придерживаться более легких решений при каждой возможности.

Итоги

Поздравляю, теперь вы обладаете могущественной силой JSON для любых ваших потребностей в Python.

Хотя примеры, с которыми вы работали, безусловно, оригинальные и чрезмерно упрощены, они демонстрируют рабочий процесс, который вы можете применить к более общим задачам:

  1. Импорт модуля json
  2. Чтение данных с load() или loads()
  3. Обработка данных
  4. Запись измененных данных при помощи dump() или dumps()

Что вы будете делать с данными, после того как они загрузились в память — зависит от вашего случая. В целом, ваша задача — собрать данные из источника, извлечение полезной информации, и передача этой информации (или ее запись).

Сегодня вы проделали небольшое путешествие: вы поймали и приручили JSON, и вернулись домой как раз к ужину! И в качестве бонуса, научившись работать с модулем json, можете начать изучение модулей pickle и marshal.

Спасибо за внимание, и удачи с вашими начинаниями в Python!

Работа с файлами в формате JSON — Документация Python для сетевых инженеров 3.0

JSON (JavaScript Object Notation) — это текстовый формат для
хранения и обмена данными.

JSON по синтаксису очень похож
на Python и достаточно удобен для восприятия.

Как и в случае с CSV, в Python есть модуль, который позволяет легко
записывать и читать данные в формате JSON.

Чтение

Файл sw_templates.json:

Для чтения в модуле json есть два метода:

  • json.load() — метод считывает файл в формате JSON и возвращает объекты Python
  • json.loads() — метод считывает строку в формате JSON и возвращает объекты Python

json.load()

Чтение файла в формате JSON в объект Python (файл json_read_load.py):

Вывод будет таким:

$ python json_read_load.py
{'access': ['switchport mode access', 'switchport access vlan', 'switchport nonegotiate', 'spanning-tree portfast', 'spanning-tree bpduguard enable'], 'trunk': ['switchport trunk encapsulation dot1q', 'switchport mode trunk', 'switchport trunk native vlan 999', 'switchport trunk allowed vlan']}
access
switchport mode access
switchport access vlan
switchport nonegotiate
spanning-tree portfast
spanning-tree bpduguard enable
trunk
switchport trunk encapsulation dot1q
switchport mode trunk
switchport trunk native vlan 999
switchport trunk allowed vlan

json.loads()

Считывание строки в формате JSON в объект Python (файл
json_read_loads.py):

Результат будет аналогичен предыдущему выводу.

Запись

Запись файла в формате JSON также осуществляется достаточно легко.

Для записи информации в формате JSON в модуле json также два метода:

  • json.dump() — метод записывает объект Python в файл в формате JSON
  • json.dumps() — метод возвращает строку в формате JSON

json.dumps()

Преобразование объекта в строку в формате JSON (json_write_dumps.py):

Метод json.dumps() подходит для ситуаций, когда надо вернуть строку в
формате JSON. Например, чтобы передать ее API.

json.dump()

Запись объекта Python в файл в формате JSON (файл json_write_dump.py):

Когда нужно записать информацию в формате JSON в файл, лучше
использовать метод dump.

Дополнительные параметры методов записи

Методам dump и dumps можно передавать дополнительные параметры для
управления форматом вывода.

По умолчанию эти методы записывают информацию в компактном
представлении. Как правило, когда данные используются другими
программами, визуальное представление данных не важно. Если же данные в
файле нужно будет считать человеку, такой формат не очень удобно
воспринимать.

К счастью, модуль json позволяет управлять подобными вещами.

Передав дополнительные параметры методу dump (или методу dumps), можно
получить более удобный для чтения вывод (файл json_write_indent.py):

Теперь содержимое файла sw_templates.json выглядит так:

{
  "access": [
    "switchport mode access",
    "switchport access vlan",
    "switchport nonegotiate",
    "spanning-tree portfast",
    "spanning-tree bpduguard enable"
  ],
  "trunk": [
    "switchport trunk encapsulation dot1q",
    "switchport mode trunk",
    "switchport trunk native vlan 999",
    "switchport trunk allowed vlan"
  ]
}

Изменение типа данных

Еще один важный аспект преобразования данных в формат JSON: данные не
всегда будут того же типа, что исходные данные в Python.

Например, кортежи при записи в JSON превращаются в списки:

In [1]: import json

In [2]: trunk_template = ('switchport trunk encapsulation dot1q',
   ...:                   'switchport mode trunk',
   ...:                   'switchport trunk native vlan 999',
   ...:                   'switchport trunk allowed vlan')

In [3]: print(type(trunk_template))
<class 'tuple'>

In [4]: with open('trunk_template.json', 'w') as f:
   ...:     json.dump(trunk_template, f, sort_keys=True, indent=2)
   ...:

In [5]: cat trunk_template.json
[
  "switchport trunk encapsulation dot1q",
  "switchport mode trunk",
  "switchport trunk native vlan 999",
  "switchport trunk allowed vlan"
]
In [6]: templates = json.load(open('trunk_template.json'))

In [7]: type(templates)
Out[7]: list

In [8]: print(templates)
['switchport trunk encapsulation dot1q', 'switchport mode trunk', 'switchport trunk native vlan 999', 'switchport trunk allowed vlan']

Так происходит из-за того, что в JSON используются другие типы данных и
не для всех типов данных Python есть соответствия.

Таблица конвертации данных Python в JSON:

PythonJSON
dictobject
list, tuplearray
strstring
int, floatnumber
Truetrue
Falsefalse
Nonenull

Таблица конвертации JSON в данные Python:

JSONPython
objectdict
arraylist
stringstr
number (int)int
number (real)float
trueTrue
falseFalse
nullNone

Ограничение по типам данных

В формат JSON нельзя записать словарь, у которого ключи — кортежи:

Работа с JSON в Python: краткое руководство

Краткое руководство по использованию JSON в Python

JSON (JavaScript Object Notation) это легковесный формат обмена данными. Людям его легко читать и вести в нем записи, а компьютеры запросто справляются с его синтаксическим анализом и генерацией.

JSON основан на языке программирования JavaScript. Но этот текстовый формат не зависит от языка и среди прочих может использоваться в Python и Perl. В основном его применяют для передачи данных между сервером и веб-приложением.

JSON построен на двух структурах:

  • Набор пар «имя-значение». Они могут быть реализованы как объект, запись, словарь, хеш-таблица, список «ключей-значений» или ассоциативный массив.
  • Упорядоченный список значений. Его реализуют в виде массива, вектора, списка или последовательности.

JSON в Python

В Python есть ряд пакетов, поддерживающих JSON, в частности metamagic.json, jyson, simplejson, Yajl-Py, ultrajson, и json. В этом руководстве мы будем использовать json, имеющий «родную» поддержку в Python. Для проверки данных JSON мы можем воспользоваться этим сайтом, предоставляющим JSON-линтер.

Ниже приведен пример записи JSON. Как видим, представление данных очень похоже на словари Python.

{
	"article": [
		{
			"id": "01",
			"language": "JSON",
			"edition": "first",
			"author": "Derrick Mwiti"
		},
		{
			"id": "02",
			"language": "Python",
			"edition": "second",
			"author": "Derrick Mwiti"
		}
	],
	"blog": [
		{
			"name": "Datacamp",
			"URL": "datacamp.com"
		}
	]
}

Конвертируем JSON в объекты Python

Вышеуказанную JSON-строку мы можем спарсить при помощи метода json.loads() из модуля json. В итоге получим словарь Python.

import json
my_json_string = """{
   "article": [

      {
         "id":"01",
         "language": "JSON",
         "edition": "first",
         "author": "Derrick Mwiti"
      },

      {
         "id":"02",
         "language": "Python",
         "edition": "second",
         "author": "Derrick Mwiti"
      }
   ],

   "blog":[
   {
       "name": "Datacamp",
       "URL":"datacamp.com"
   }
   ]
}
"""
to_python = json.loads(my_json_string)
to_python['blog']
[{'URL': 'datacamp.com', 'name': 'Datacamp'}]

Конвертируем объекты Python в JSON

Используя json.dumps(), мы можем сконвертировать объекты Python в формат JSON.

blog = {'URL': 'datacamp.com', 'name': 'Datacamp'}
to_json= json.dumps(blog)
to_json
'{"URL": "datacamp.com", "name": "Datacamp"}'

Теперь давайте сравним типы данных в Python и JSON.

Python JSON
dict Object
list Array
tuple Array
str String
int Number
float Number
True true
False false
None null

Ниже мы покажем, как сконвертировать некоторые объекты Python в типы данных JSON.

Кортеж Python — в массив JSON
tuple_example = 'Mango', 'Banana', 'Apple'
print(json.dumps(tuple_example))
["Mango", "Banana", "Apple"]
Список Python — в массив JSON
list_example = ["Mango", 1, 3, 6, "Oranges"]
print(json.dumps(list_example))
["Mango", 1, 3, 6, "Oranges"]
Строка Python — в строку JSON
string_example = "This is a cool example."
print(json.dumps(string_example))
"This is a cool example."
Булевы значения Python — в булевы значения JSON
boolean_value = False
print(json.dumps(boolean_value))
false

Запись в файл JSON

Модуль json позволяет также записывать данные JSON в файл. Такие файлы сохраняют с расширением .json.

Давайте посмотрим, как это сделать. Для этого воспользуемся функцией open() с параметром w, сигнализирующим о том, что мы хотим записать в файл.

my_json_string = """{
   "article": [

      {
         "id":"01",
         "language": "JSON",
         "edition": "first",
         "author": "Derrick Mwiti"
      },

      {
         "id":"02",
         "language": "Python",
         "edition": "second",
         "author": "Derrick Mwiti"
      }
   ],

   "blog":[
   {
       "name": "Datacamp",
       "URL":"datacamp.com"
   }
   ]
}
"""
with open('test_file.json', 'w') as file:
    json.dump(my_json_string, file)

Чтение файлов JSON

Теперь продемонстрируем, как прочитать только что созданный нами файл JSON. Для его загрузки вызовем json.load().

with open('test_file.json', 'r') as j:
    json_data = json.load(j)
    print(json_data)
{
   "article": [

      {
         "id":"01",
         "language": "JSON",
         "edition": "first",
         "author": "Derrick Mwiti"
      },

      {
         "id":"02",
         "language": "Python",
         "edition": "second",
         "author": "Derrick Mwiti"
      }
   ],

   "blog":[
   {
       "name": "Datacamp",
       "URL":"datacamp.com"
   }
   ]
}
json.load vs json.loads

json.load используют для загрузки файла, а json.loads – для загрузки строки (loads расшифровывается как «load string»).

json.dump vs json.dumps

Аналогично, json.dump применяется, если нужно сохранить JSON в файл, а json.dumps (dump string) – если данные JSON нам нужны в виде строки для парсинга или вывода.

Работа с данными JSON в Data Science

Иногда при работе над проектами, связанными с data science, требуется загрузить данные в формате JSON. Библиотека для анализа данных Pandas предоставляет для этого функцию .read_json. Как только данные загружены, мы конвертируем их в объект dataframe при помощи атрибута pandas.DataFrame.

import pandas as pd
data = pd.read_json("https://api.github.com/users")
df = pd.DataFrame(data)
df

Ограничения имплементации

Процесс кодирования в JSON называется сериализацией, а декодирования – десериализацией.
Некоторые реализации десериализаторов имеют ограничения на:

  • размер принимаемых текстов JSON
  • максимальный уровень вложенности объектов и массивов JSON
  • диапазон точности чисел JSON
  • содержание и максимальную длину строк JSON.

Впрочем, подобные ограничения связаны только с типами данных Python и работой самого интерпретатора Python.

Формат JSON в разработке API

Одно из важнейших применений JSON – для разработки API в веб-приложениях. Этот формат очень полезен, ведь позволяет коллегам-разработчикам строить систему на основе наших API, используя любой язык, поддерживающий JSON. А такой поддержкой обладают практически все современные языки. На простом примере покажем, как вернуть JSON при разработке приложения на Python с фреймворком Flask. Flask предоставляет для этого модуль jsonify.

from flask import jsonify


@app.route('/_get_current_user')
def get_current_user():
    return jsonify(username=g.user.username,
                   email=g.user.email,
                   id=g.user.id)

Эта программа отправит в браузер что-то вроде следующего:

{
	"username": "Derrick Mwiti",
	"email": "[email protected]",
	"id": 1
}
{'email': '[email protected]', 'id': 1, 'username': 'Derrick Mwiti'}

Заключение

В этом уроке мы сделали небольшое введение в особенности работы с JSON в Python. Рассмотрели использование различных методов из модуля json, таких как json.load и json.dumps. Кроме того, мы разобрали, как загрузить данные в формате JSON для работы в проектах data science и как возвращать JSON при разработке API. Узнать больше о модуле json можно на его официальной странице на сайте Python.

JSON в python для начинающих, конвертация и методы ~ PythonRu

Предыдущий урок: Даты в Python

JSON является синтаксисом для хранения и обмена данными. JSON — это текст, написанный в стиле объекта JavaScript.

JSON в Python

Python имеет встроенный модуль json, который может использоваться для работы с данными JSON.

import json

Полная документация по модулю JSON для Python 3 на русском: Модуль JSON Python для работы с форматом .json

Конвертация из JSON в Python

Если у вас есть строка JSON, вы можете провести над ней парсинг с помощью метода json.loads ().
Как результат, будет словарь python.
Конвертируем из JSON в Python:

import json


x = '{"name":"Viktor", "age":30, "city":"Minsk"}'

y = json.loads(x)

print(y["age"])

Вывод:

30

Конвертировать из Python в JSON

Если у вас есть объект Python, вы можете преобразовать его в строку JSON с помощью метода json.dumps().

import json


x = {
"name": "Viktor",
"age": 30,
"city": "Minsk"
}

y = json.dumps(x)

print(y)

Вывод:

{"name": "Viktor", "age": 30, "city": "Minsk"}

Вы можете преобразовать следующие типов объекты Python в строки JSON:

  • dict
  • list
  • tuple
  • string
  • int
  • float
  • True
  • False
  • None

Конвертируем объекты Python в строки JSON и выведите значения:

import json
  
print(json.dumps({"name": "Viktor", "age":  30}))
print(json.dumps(["Porsche", "BMW"]))
print(json.dumps(("Porsche", "BMW")))
print(json.dumps("hello"))
print(json.dumps(42))
print(json.dumps(31.76))
print(json.dumps(True))
print(json.dumps(False))
print(json.dumps(None))
Подписывайтесь на телеграм каналы

Вывод:

{"name": "Viktor", "age": 30}
["Porsche", "BMW"]
["Porsche", "BMW"]
"hello"
42
31.76
true
false
null

Когда вы конвертируете из Python в JSON, объекты Python преобразуются в эквивалент JSON:

PythonJSON
dictObject
listArray
tupleArray
strString
intNumber
floatNumber
Truetrue
Falsefalse
Nonenull

Конвертируйте объект Python, содержащий все типы конвертируемых данных:

import json

x = {
"name": "Viktor",
"age": 30,
"married": True,
"divorced": False,
"children": ("Anna","Bogdan"),
"pets": None,
"cars": [
{"model": "BMW 230", "mpg":  27.5},
{"model": "Ford Edge", "mpg": 24.1}  
]
}
print(json.dumps(x))

Вывод:

{"name": "Viktor", "age": 30, "married": true, "divorced": false, "children": ["Anna", "Bogdan"], "pets": null, "cars": [{"model": "BMW 230", "mpg": 27.5}, {"model": "Ford Edge", "mpg": 24.1}]}

Как конвертировать кириллицу

Если в данных Python есть символы кириллицы, метод json.dumps() преобразует их с кодировкой по умолчанию. Что бы сохранить кириллицу используйте параметр ensure_ascii=False

import json

x = {
"name": "Виктор"
}
y = {
"name": "Виктор"
}
print(json.dumps(x))
print(json.dumps(y, ensure_ascii=False))

Вывод:

{"name": "\u0412\u0438\u043a\u0442\u043e\u0440"}
{"name": "Виктор"}

Форматирование результата

В приведенном выше примере выводится строка JSON, но читать ее не так просто, без отступов и переносов строк.

У метода json.dumps() есть параметры, облегчающие чтение результата.
Используем параметр indent для определения количества отступов:

json.dumps(x, indent=4) 

Вы также можете определить разделители, значение которых по умолчанию — ,, :, где запятая и пробел используются для разделения каждого объекта, а двоеточие и пробел — для разделения ключей и значений.
Используем параметр separators чтобы изменить разделитель по умолчанию:

json.dumps(x, indent=4, separators=(". ", " = "))

Упорядочивание результата

Метод json.dumps() имеет параметры для упорядочивания ключей в результате.
Используем параметр sort_keys чтобы указать, должен ли сортироваться результат.

json.dumps(x, indent=4, sort_keys=True)

Далее: Регулярные выражения в Python

Документация модуля JSON для Python 3 на русском ~ PythonRu

JSON (JavaScript Object Notation-формат передачи данных), определен стандартом RFC 7159 (который является устаревшей версией RFC 4627) и ECMA-404, легким текстовым форматом обмена данных, основанным на синтаксисе литералов объекта JavaScript (хотя он и не является подгруппой JavaScript).

json предоставляет API, знакомый пользователям стандартных библиотечных модулей marshal и pickle.

Кодировка иерархии базовых объектов в Python:

>>> import json
>>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
'["foo", {"bar": ["baz", null, 1.0, 2]}]'
>>> print(json.dumps("\"foo\bar"))
"\"foo\bar"
>>> print(json.dumps('\u1234'))
"\u1234"
>>> print(json.dumps('\\'))
"\\"
>>> print(json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True))
{"a": 0, "b": 0, "c": 0}
>>> from io import StringIO
>>> io = StringIO()
>>> json.dump(['streaming API'], io)
>>> io.getvalue()
'["streaming API"]'

Компактная кодировка:

>>> import json
>>> json.dumps([1, 2, 3, {'4': 5, '6': 7}], separators=(',', ':'))
'[1,2,3,{"4":5,"6":7}]'

Красивый вывод:

>>> import json
>>> print(json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4))
{
 "4": 5,
 "6": 7
}

Декодирование JSON:

>>> import json
>>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
['foo', {'bar': ['baz', None, 1.0, 2]}]
>>> json.loads('"\\"foo\\bar"')
'"foo\x08ar'
>>> from io import StringIO
>>> io = StringIO('["streaming API"]')
>>> json.load(io)
['streaming API']

Специализированное декодирование объектов в JSON:

>>> import json
>>> def as_complex(dct):
...     if '__complex__' in dct:
...         return complex(dct['real'], dct['imag'])
...     return dct
...
>>> json.loads('{"__complex__": true, "real": 1, "imag": 2}',
...     object_hook=as_complex)
(1+2j)
>>> import decimal
>>> json.loads('1.1', parse_float=decimal.Decimal)
Decimal('1.1')

Расширение JSONEncoder:

>>> import json
>>> class ComplexEncoder(json.JSONEncoder):
...     def default(self, obj):
...         if isinstance(obj, complex):
...             return [obj.real, obj.imag]
...         
...         return json.JSONEncoder.default(self, obj)
...
>>> json.dumps(2 + 1j, cls=ComplexEncoder)
'[2.0, 1.0]'
>>> ComplexEncoder().encode(2 + 1j)
'[2.0, 1.0]'
>>> list(ComplexEncoder().iterencode(2 + 1j))
['[2.0', ', 1.0', ']']
Подписывайтесь на телеграм каналы

Рекомендуется использование json.tool для проверки и красивого вывода:

$ echo '{"json": "obj"}' | python -m json.tool
{
 "json": "obj"
}
$ echo '{1.2:3.4}' | python -m json.tool
Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

JSON является подмножеством YAML 1.2 JSON создан с помощью стандартных настроек этого модуля и также является подмножеством YAML 1.0 and 1.1. Этот модуль может использоваться в качестве сериализатора YAML.

Основы пользования

Метод json.dump

json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

Сериализует obj в JSON-подобный формат записывая его в fp (который поддерживает .write()) используя эту таблицу.

Если skipkeys=True (по умолчанию: False), тогда ключи словаря не базового типа (str, int, float, bool, None) будут пропущены, вместо того, чтобы вызывать исключение TypeError.

Модуль json всегда создает объекты str, не bytes. Следовательно, fp.write() должен поддерживать ввод str.

Когда ensure_ascii=True (по умолчанию), все не-ASCII символы в выводе будут экранированы последовательностями \uXXXX,. Если ensure_ascii=False, эти символы будут записаны как есть.

Когда check_circular=False (по умолчанию: True), тогда проверка циклических ссылок для типов контейнера будет пропущена, а такие ссылки будут вызывать OverflowError (или ошибку серьёзнее).

Если allow_nan=False (по умолчанию: True), при каждой попытке сериализировать значение float, выходящее за допустимые пределы (nan, inf, -inf), будет возникать ValueError, в соответствии с сертификацией JSON. В случае если allow_nan=True, будут использованы JavaScript аналоги (NaN, Infinity, -Infinity).

Когда indent является неотрицательным целым числом или строкой, то объекты и массивы JSON будут выводиться с этим количеством отступов. Если уровень отступа равен 0, отрицательный или "", будут использоваться новые строки без отступов. None (по умолчанию) отражает наиболее компактное представление. Если indent строка (например, "\t"), эта строка используется в качестве отступа.

Изменения в версии 3.2: Допускаются строки для отступа в дополнение к целым числам.

Separators должны быть tuple (item_separator, key_separator). По умолчанию используется значение (', ', ': ') если indent=None и (',', ': ') при другом значении. Чтобы получить наиболее компактное представление JSON, вы должны указать (',', ':').

Изменения в версии 3.4: Используйте(',', ': ') при отступе None.

Значение default должно быть функцией. Он вызывается для объектов, которые не могут быть сериализованы. Функция должна вернуть кодируемую версию объекта JSON или вызывать TypeError. Если default не указано, возникает ошибка TypeError.

Если sort_keys=True (по умолчанию: False), ключи выводимого словаря будут отсортированы.

Чтобы использовать собственный подкласс JSONEncoder (например, тот который переопределяет метод default() для сериализации дополнительных типов), укажите его с помощью аргумента cls; в противном случае используется JSONEncoder.

Метод json.dumps

json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

Сериализирует obj в строку str формата JSON с помощью таблицы конвертации. Аргументы имеют то же значение, что и для dump().

Примечание: Ключи в парах ключ/значение всегда являются строками. Когда словарь конвертируется в JSON, все ключи словаря преобразовываются в строки. Если в результате, сначала конвертировать его в JSON, а потом обратно, новый в словарь может отличаться от, то можно получить словарь идентичный исходному. Другими словами, loads(dumps(x)) != x если x имеет не строковые ключи.

Метод json.load

json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

Десериализует из fp (текстовый или бинарный файл, который поддерживает метод .read() и содержит JSON документ) в объект Python используя эту таблицу конвертации.

object_hook — опциональная функция, которая применяется к результату декодирования объекта. Использоваться будет значение, возвращаемое этой функцией, а не полученный словарь dict. Эта функция используется для реализации пользовательских декодеров (например JSON-RPC).

object_pair_shook — опциональная функция, которая применяется к результату декодирования объекта с определенной последовательностью пар ключ/значение. Вместо исходного словаря dict будет использоваться результат, возвращаемый функцией. Эта функция используется для реализации пользовательских декодеров. Если задан object_hook, object_pairs_hook будет в приоритете.

В случае определения parse_float, он будет вызван для каждого значения JSON с плавающей точкой. По умолчанию, это эквивалентно float(num_str). Можно использовать другой тип данных или парсер для этого значения (например decimal.Decimal)

В случае определения parse_int, он будет вызван для декодирования строк JSON int. По умолчанию, эквивалентен int(num_str). Можно использовать другой тип данных или парсер для этого значения (например float).

В случае определения parse_constant, он будет вызван для строк: -Infinity, Infinit, NaN. Может быть использован для вызова исключений при обнаружении недопустимых чисел JSON. parse_constant больше не вызывается при null, true, fasle.

Чтобы использовать собственный подкласс JSONDecoder, укажите его с помощью аргумента cls; в противном случае используется JSONDecoder. Дополнительные аргументы ключевого слова будут переданы конструктору класса.

Если десериализованные данные не являются допустимым документом JSON, возникнет JSONDecodeError.

Метод json.loads

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

Десериализует s (экземпляр str, bytes или bytearray, содержащий JSON документ) в объект Python используя таблицу конвертации.

Остальные аргументы аналогичны аргументам в load(), кроме кодировки, которая устарела либо игнорируется.

Если десериализованные данные не являются допустимым документом JSON, возникнет ошибка JSONDecodeError.

Кодировщики и декодировщики

JSONDecoder

Класс json.JSONDecoder(*, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, strict=True, object_pairs_hook=None)

Простой декодер JSON.
При декодировании выполняет следующие преобразования:

JSONPython
objectdict
arraylist
stringstr
number (int)int
number (real)float
trueTrue
falseFalse
nullNone

Он также понимает NaN, Infinity, и -Infinity как соответствующие значения float, которые находятся за пределами спецификации JSON.

object_hook будет вызван для каждого значения декодированного объекта JSON, а его возвращаемое значение будет использовано в указанном месте dict. Может быть использовано для обеспечения десериализации (например, для поддержки JSON-RPC class hinting).

object_pairs_hook будет вызван для каждого значения декодированного объекта JSON с упорядоченным списком пар. Возвращаемое значение object_pairs_hook будет использовано вместо dict. Эта функция может использоваться для запуска стандартного декодера. Если object_hook так же определён, в приоритете будет object_pairs_hook.

parse_float будет вызван для каждого значения JSON с плавающей точкой. По умолчанию, это эквивалентно float(num_str). Может быть использован для другого типа данных или парсера JSON float. (например, decimal.Decimal).

parse_int будет вызван для строки JSON int. По умолчанию, эквивалентно int(num_str). Может быть использован для других типов данных и парсеров целых чисел JSON (например, float).

parse_constant будет вызван для строк: '-Infinity', 'Infinity', 'NaN'. Можно  использовать для вызова исключений при обнаружении недопустимых чисел JSON.

Если strict=False (True по умолчанию), тогда использование управляющих символов внутри строк будет разрешено. В данном контексте управляющие символы — это символы с кодами в диапазоне 0–31, включая \t (tab), \n, \r и \0.

Если десериализованные данные не являются допустимым документом JSON, будет вызвана ошибка JSONDecodeError.

decode(s)
Возвращает представление s в Python (str — содержащий документ JSON). JSONDecodeError будет вызвана, если документ JSON не валидный (или не действительный).

raw_decode(s)
Декодирует документ JSON из s (str начинающийся с JSON документа) и возвращает кортеж из 2-х элементов (представление Python и индекс строки в s, на которой закончился документ). Может использоваться для декодирования документа JSON из строки, которая имеет дополнительные данные в конце.

JSONEncoder

Класс json.JSONEncoder(*, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)

Расширяемый кодировщик JSON для структур данных Python.
Поддерживает следующие типы данных и объекты по умолчанию:

PythonJSON
dictobject
list, tuplearray
strstring
int, floatnumber
Truetrue
Falsefalse
Nonenull

Для того, чтобы можно было распознавать и другие объекты, подкласс должен выполнить метод default(), который вернет сериализуемый объект для o, если это возможно, в противном случае он должен вызвать реализацию родительского класса (для вызова TypeError).

Если skipkeys=False (по умолчанию), вызывается TypeError при попытке кодировать ключи, которые не являются str, int, float или None. В случае если skipkeys=True, такие элементы просто пропускаются.

Если ensure_ascii=True (по умолчанию), на выходе гарантируется, что все входящие не ASCII символы экранируются последовательностями \uXXXX. Но если ensure_ascii=False, эти символы будут выводиться как есть.

Если check_circular=True (по умолчанию), тогда списки, словари и самостоятельно закодированные объекты будут проверяться на циклические ссылки во время кодировки, чтобы предотвратить бесконечную рекурсию (что вызовет OverflowError). В другом случае, такая проверка не выполняется.

Если allow_nan=True (по умолчанию), тогда NaN, Infinity, и -Infinity будут кодированы как таковые. Это не соответствует спецификации JSON, но соответствует большинству кодировщиков и декодеров на основе JavaScript. В другом случае такие значения вызовут ValueError.

Если sort_keys=True (по умолчанию: False), выводимый словарь будет отсортирован по именам ключей; это полезно для регрессивного тестирования, чтобы сравнивать сериализацию JSON ежедневно.

Если indent является неотрицательным целым числом или строкой, то объекты и массивы JSON будут выводиться с этим количеством отступов. Если уровень отступа равен 0, отрицательный или "", будут использоваться новые строки без отступов. None (по умолчанию) отражает наиболее компактное представление. Если indent строка (например, "\t"), эта строка используется в качестве отступа.

Если указан separator (должен быть tuple типа (item_separator, key_separator)). По умолчанию используется (', ', ': ') если indent=None и (',', ': ') если нет. Для получения наиболее компактного представления JSON , вам следует использовать (',', ':'), чтобы уменьшить количество пробелов.

Значение default должно быть функцией. Она вызывается для объектов, которые не могут быть сериализованы. Функция должна вернуть кодируемую версию объекта JSON или вызывать TypeError. Если default не указано, возникает ошибка TypeError.

default(o)
Внедрите этот метод в подкласс таким образом, чтобы он возвращал сериализуемый объект для o или вызывал базовую реализацию (для повышения TypeError).
Например, чтобы поддерживать произвольные итераторы, вы можете реализовать default следующим образом:

def default(self, o):
   try:
       iterable = iter(o)
   except TypeError:
       pass
   else:
       return list(iterable)
   
   return json.JSONEncoder.default(self, o)

encode(o)
Возвращает строковое представление JSON структуры данных Python. Пример:

json.JSONEncoder().encode({"foo": \["bar", "baz"\]})
'{"foo": \["bar", "baz"\]}'

iterencode(o)
Кодирует переданный объект o и выдаёт каждое строковое представление, как только оно становится доступным. Например:

for chunk in json.JSONEncoder().iterencode(bigobject):
    mysocket.write(chunk)

Исключение JSONDecodeError

Исключение json.JSONDecodeError(msg, doc, pos)
Подкласс ValueError с дополнительными атрибутами:

msg — не отформатированное сообщение об ошибке.
doc — парсинг JSON документа.
pos — первый индекс doc, если парсинг неудачный.
lineno — строка, соответствующая pos.
colno — колонка, соответствующая pos.

Стандартное соответствие и совместимость

Формат JSON указан в RFC 7159 и ECMA-404. В этом разделе описывается уровень соответствия этого модуля с RFC. Для упрощения, подклассы JSONEncoder и JSONDecoder, и параметры, которые отличаются от указанных, не берутся во внимание.

Этот модуль не соответствует RFC, устанавливая некоторые расширения, которые являются рабочими для JavaScript, но недействительными для JSON. В частности:

  • Infinite и NaN принимаются и выводятся;
  • Повторяемые имена внутри объекта принимаются и выводятся, но только последнее значение дублируемого ключа.

Поскольку RFC разрешает синтаксическим анализаторам, совместимым с RFC, принимать входные тексты, которые не соответствуют требованиям RFC, десериализатор этого модуля технически соответствует стандартным настройкам RFC.

Кодировка символов

RFC требует, чтобы JSON был представлен с использованием UTF-8, UTF-16 или UTF-32, при том, что UTF-8 является рекомендуемым по умолчанию для максимальной совместимости.

Возможно, но не обязательно для RFC, сериализаторы этого модуля устанавливают ensure_ascii=True по умолчанию, таким образом строки содержат только символы ASCII.

Кроме параметра ensure_ascii, этот модуль напрямую не затрагивает проблему кодировки символов.

RFC запрещает маркер последовательности байтов (BOM) в начало текста JSON и сериализатор этого модуля не добавляет BOM. RFC позволет, не не требует десериализаторы JSON игнорировать BOM на входе. Десериализатор этого модуля вызывает ValueError при наличии BOM.

RFC явно не запрещает строки JSON, содержащие последовательность байт, которая не соответствует валидным символам Unicode (например, непарные UTF-16 заменители), он отмечает — они могут вызывать проблемы совместимости. По умолчанию этот модуль принимает и выводит (если есть в исходной строке) специальные последовательности кода.

Infinite и NaN

RFC не допускает представления для значений infinite или NaN. Несмотря на это, по умолчанию этот модуль принимает и выводит Infinity, -Infinity, и NaN, как если бы они были действительно буквальными значениями числа в JSON:

>>> 
>>> json.dumps(float('-inf'))
'-Infinity'
>>> json.dumps(float('nan'))
'NaN'
>>> 
>>> json.loads('-Infinity')
-inf
>>> json.loads('NaN')
nan

В сериализаторе параметр allow_nan используется для изменения этого поведения. В десериализаторе параметр этот переметр — parse_constant.

Повторяющиеся имена внутри объекта

RFC указывает, что имена в объекте JSON должны быть уникальными, но не указывает, как должны обрабатываться повторяющиеся имена в объектах JSON. По умолчанию этот модуль не вызывает исключения; вместо этого он игнорирует все, кроме последней пары ключ/значение для данного ключа:

>>> weird_json = '{"x": 1, "x": 2, "x": 3}'
>>> json.loads(weird_json)
{'x': 3}

Параметр object_pairs_hook может использоваться для изменения этого.

Значение верхнего уровня Non-Object, Non-Array

Старая версия JSON указанная устаревшим RFC 4627 требовала, чтобы значение верхнего уровня текста JSON было объектом JSON или массивом (Python dict или list), или не было JSON null, boolean, number, string value. RFC 7159 убрало это ограничение, поэтому этот модуль не выполнял и никогда не применял это ограничение ни в своем сериализаторе, ни в десериализаторе.

Тем не менее, для максимальной совместимости, вы можете добровольно придерживаться этого ограничения.

Ограничения реализации

Некоторые реализации десериализатора JSON имеют лимиты на:

  • размер принимаемого текста JSON
  • максимальный уровень вложенности объектов и массивов JSON
  • диапазон и точность чисел JSON
  • содержание и максимальная длина строк JSON

Этот модуль не ставит никаких ограничений, кроме тех, которые относятся к соответствующим типам Python или самому интерпретатору Python.

При сериализации в JSON будьте осторожны с такими ограничениями в приложениях, которые могут потреблять ваш JSON. В частности, числа в JSON часто десериализуются в числа двойной точности IEEE 754 и подвержены ограничениям диапазона и точности этого представления. Это особенно актуально при сериализации значений Python int чрезвычайно большой величины или при сериализации экземпляров «необычных» числовых типов, таких как decimal.Decimal.

Интерфейс командной строки

Исходный код: Lib/json/tool.py

Модуль json.tool обеспечивает простой интерфейс командной строки для проверки и вывода объектов JSON.

Если не обязательные аргументы infile и outfile не указаны, sys.stdin и sys.stdout будут соответственно:

$ echo '{"json": "obj"}' | python -m json.tool
{
 "json": "obj"
}
$ echo '{1.2:3.4}' | python -m json.tool
Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

Возможности командной строки

infile
Проверки и красивого вывод файла JSON:

$ python -m json.tool mp_films.json
[
	{
		"title": "And Now for Something Completely Different",
		"year": 1971
	},
	{
		"title": "Monty Python and the Holy Grail",
		"year": 1975
	}
]

Если infile не указан, чтение из sys.stdin.

outfile
Запишет вывод из infile в данный outfile. В противном случае, запишет его в sys.stdout.

--sort-keys
Сортировка выводимых словарей в алфавитном порядке по ключам.

-h, --help
Показать справку.

Работа с данными JSON в Python

Подписывайся на наш канал в Telegram, чтобы ежедневно совершенствоваться в Python. Там выходят задачи, полезные советы и сливы платных курсов — перейти

Оглавление

  • Краткая история JSON
  • Смотри, это JSON!
  • Python поддерживает JSON изначально!
    • Немного словарного запаса
    • Сериализация JSON
    • Простой пример сериализации
    • Некоторые полезные аргументы ключевого слова
    • Десериализация JSON
    • Простой пример десериализации
  • Пример из реального мира
  • Кодирование и декодирование пользовательских объектов Python
    • Упрощение структур данных
    • Кодирование пользовательских типов
    • Расшифровка пользовательских типов
  • Все сделано!

С самого начала JSON стал стандартом фактически для обмена информацией. Скорее всего, вы здесь, потому что вам нужно перенести некоторые данные из одного места в другое. Возможно, вы собираете информацию через API или храните свои данные в базе данных документов . Так или иначе, вы по уши в JSON и у вас есть выход на Python.

К счастью, это довольно распространенная задача, и, как и в случае большинства обычных задач, Python делает ее почти максимально легкой.

Итак, мы используем JSON для хранения и обмена данными? Да, ! Это не более чем стандартный формат, который сообщество использует для передачи данных. Имейте в виду, JSON – не единственный формат, доступный для такого рода работы, но есть XML и YAML , вероятно, единственные, которых стоит упомянуть в одном ряду.

Краткая история JSON

Не так удивительно,J avaS cript O bject N otation был вдохновлен подмножеством языка программирования JavaScript, имеющим дело с литеральным синтаксисом объекта. У них есть отличный сайт, который объясняет все это. Не беспокойтесь: JSON уже давно стал независимым от языка и существует как собственный стандарт, поэтому, к счастью, мы можем избежать использование JavaScript.

В конечном счете, сообщество в целом приняло JSON, потому что людям и машинам легко создавать и понимать.

Смотри, это JSON!

Приготовьтесь, мы покажем вам немного реальной жизни JSON – точно так же, как вы видели бы там в дикой природе. Это нормально: JSON должен быть доступен для чтения любому, кто использовал язык C-стиля, а Python таковым является!

{
    "firstName": "Jane",
    "lastName": "Doe",
    "hobbies": ["running", "sky diving", "singing"],
    "age": 35,
    "children": [
        {
            "firstName": "Alice",
            "age": 6
        },
        {
            "firstName": "Bob",
            "age": 8
        }
    ]
}

Как видите, JSON поддерживает примитивные типы, такие как строки и числа, а также вложенные списки и объекты.

Подождите, это похоже на словарь Python! Ведь да? На данный момент это довольно универсальная запись объектов, но я не думаю, что UON скатывается с языка так же хорошо.

Уф! Вы пережили свою первую встречу с каким-то диким JSON. Теперь вам просто нужно научиться приручать его.

Python поддерживает JSON изначально!

Python поставляется со встроенным пакетом json, предназначенным  для кодирования и декодирования данных JSON.

Просто подбросьте этого маленького парня вверху вашего файла:

import json

Немного словарного запаса

Процесс кодирования JSON обычно называется сериализацией . Этот термин относится к преобразованию данных в серию байтов (следовательно, последовательных ) для хранения или передачи по сети. Вы также можете услышать термин маршалинг , но это совсем другое. Естественно, десериализация – это взаимный процесс декодирования данных, которые были сохранены или доставлены в стандарте JSON.

Хлоп! Это звучит довольно технически. Определенно. Но на самом деле все, о чем мы здесь говорим – это чтение и письмо . Думайте об этом так: кодирование предназначено для записи данных на диск, а декодирование – для чтения данных в память.

Сериализация JSON

Что происходит после того, как компьютер обрабатывает много информации? Нужно взять дамп данных. Соответственно, json библиотека предоставляет dump() способ записи данных в файлы. Существует также dumps() метод (произносится как «dump-s») для записи в строку Python.

Простые объекты Python переводятся в JSON в соответствии с довольно интуитивным преобразованием.

PythonJSON
dictobject
listtuplearray
strstring
intlong,floatnumber
Truetrue
Falsefalse
Nonenull

Простой пример сериализации

Представьте, что вы работаете с объектом Python в памяти, который выглядит примерно так:

data = {
    "president": {
        "name": "Zaphod Beeblebrox",
        "species": "Betelgeusian"
    }
}

Крайне важно сохранить эту информацию на диске, поэтому ваша задача – записать ее в файл.

Используя менеджер контекста Python, вы можете создать файл с именем data_file.json и открыть его в режиме записи. (Файлы JSON заканчиваются .json расширением.)

with open("data_file.json", "w") as write_file:
    json.dump(data, write_file)

Обратите внимание, что dump() принимает два позиционных аргумента: (1) объект данных для сериализации и (2) файлоподобный объект, в который будут записаны байты.

Или, если вы склонны продолжать использовать эти сериализованные данные JSON в своей программе, вы можете записать их в собственный str объект Python .

json_string = json.dumps(data)

Обратите внимание, что файлоподобный объект отсутствует, поскольку вы фактически не записываете на диск. Кроме этого, dumps() аналогичен dump().

Ура! Вы родили маленького мальчика JSON, и вы готовы выпустить его в дикую природу, чтобы он стал большим и сильным.

Некоторые полезные аргументы ключевого слова

Помните, что JSON должен быть легко читаемым людьми, но читаемый синтаксис не достаточен, если все это сжато вместе. Кроме того, у вас, вероятно, другой стиль программирования, чем у меня, и вам может быть легче читать код, когда он отформатирован по вашему вкусу.

ПРИМЕЧАНИЕ. Оба метода и используют dump() и dumps() одни и те же ключевые аргументы.

Первый вариант, который большинство людей хотят изменить, – это пробел. Вы можете использовать ключевое слово indent , чтобы указать размер отступа для вложенных структур. Проверьте разницу, используя data, который мы определили выше, запустив в консоли следующие команды:

>>> json.dumps(data)
>>> json.dumps(data, indent=4)

Другим вариантом форматирования является ключевое слово separators . По умолчанию это две строки разделителей (", ", ": "), но распространенной альтернативой для компактного JSON является (",", ":"). Посмотрите на образец JSON еще раз, чтобы увидеть, где эти разделители вступают в игру.

Есть и другие, sort_keys но я понятия не имею, что этот человек делает. Вы можете найти весь список в документах, если вам интересно.

Десериализация JSON

Теперь пришло время привести его в форму. В json библиотеке вы найдете load() и loads() для преобразования закодированных данных JSON в объекты Python.

Как и в случае с сериализацией, для десериализации существует простая таблица преобразования, хотя вы, вероятно, уже догадались, как она выглядит.

JSONPython
objectdict
arraylist
stringstr
number (целый)int
number (действительный)float
trueTrue
falseFalse
nullNone

Технически, это преобразование не является совершенной противоположностью таблице сериализации. По сути, это означает, что если вы кодируете объект сейчас, а потом декодируете его позже, вы не сможете получить точно такой же объект обратно. Я полагаю, это немного похоже на телепортацию: разбейте мои молекулы здесь и соедините их там. Я все еще тот же человек?

В действительности, это скорее похоже на то, как один друг переводит что-то на японский, а другой – обратно на русский. В любом случае, простейшим примером будет кодирование tuple и возврат list после декодирования, например так:

>>> blackjack_hand = (8, "Q")
>>> encoded_hand = json.dumps(blackjack_hand)
>>> decoded_hand = json.loads(encoded_hand)

>>> blackjack_hand == decoded_hand
False
>>> type(blackjack_hand)
<class 'tuple'>
>>> type(decoded_hand)
<class 'list'>
>>> blackjack_hand == tuple(decoded_hand)
True

Простой пример десериализации

На этот раз представьте, что на диске хранятся некоторые данные, которыми вы хотите манипулировать в памяти. Вы по-прежнему будете использовать менеджер контекста, но на этот раз вы откроете существующий data_file.json в режиме чтения.

with open("data_file.json", "r") as read_file:
    data = json.load(read_file)

Здесь все довольно просто, но имейте в виду, что результат этого метода может вернуть любой из разрешенных типов данных из таблицы преобразования. Это важно, только если вы загружаете данные, которые раньше не видели. В большинстве случаев корневым объектом будет dict или list.

Если вы извлекли данные JSON из другой программы или иным образом получили строку данных в формате JSON в Python, вы можете легко десериализовать их с помощью loads(), которая естественным образом загружается из строки:

json_string = """
{
    "researcher": {
        "name": "Ford Prefect",
        "species": "Betelgeusian",
        "relatives": [
            {
                "name": "Zaphod Beeblebrox",
                "species": "Betelgeusian"
            }
        ]
    }
}
"""
data = json.loads(json_string)

Вуаля!

Пример из реального мира (sort of)

В качестве вводного примера вы будете использовать JSONPlaceholder, отличный источник поддельных данных JSON для практических целей.

Сначала создайте файл сценария с именем scratch.py или по желанию. 

Вам нужно будет сделать запрос API к службе JSONPlaceholder, поэтому просто используйте requests пакет для выполнения тяжелой работы. Добавьте этот импорт вверху вашего файла:

import json
import requests

Теперь вы будете работать со списком TODO, потому что … вы знаете, это обряд или что-то в этом роде.

Продолжайте и сделайте запрос к API JSONPlaceholder для конечной точки /todos . Если вы не знакомы с requests, на самом деле есть удобный json() метод, который сделает всю работу за вас, но вы можете попрактиковаться в использовании json библиотеки для десериализации text атрибута ответа объекта . Это должно выглядеть примерно так:

response = requests.get("https://jsonplaceholder.typicode.com/todos")
todos = json.loads(response.text)

Вы не верите, что это работает? Хорошо, запустите файл в интерактивном режиме и проверьте его сами. Проверьте тип todos. Если вы чувствуете себя авантюрным, взгляните на первые 10 или около того пунктов в списке.

>>> todos == response.json()
True
>>> type(todos)
<class 'list'>
>>> todos[:10]
...

Что такое интерактивный режим? Вы знаете, как вы всегда прыгаете вперед и назад между вашим редактором и терминалом? Что ж, мы, подлые питонисты, используем интерактивный флаг -i , когда запускаем скрипт. Это отличный маленький трюк для тестирования кода, потому что он запускает скрипт, а затем открывает интерактивную командную строку с доступом ко всем данным из скрипта!

Хорошо, время для некоторых действий. Вы можете увидеть структуру данных, посетив конечную точку в браузере, но вот пример TODO:

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

Есть несколько пользователей, каждый с уникальным userId, и каждая задача имеет логическое completed свойство. Можете ли вы определить, какие пользователи выполнили больше всего задач?

# Map of userId to number of complete TODOs for that user
todos_by_user = {}

# Increment complete TODOs count for each user.
for todo in todos:
    if todo["completed"]:
        try:
            # Increment the existing user's count.
            todos_by_user[todo["userId"]] += 1
        except KeyError:
            # This user has not been seen. Set their count to 1.
            todos_by_user[todo["userId"]] = 1

# Create a sorted list of (userId, num_complete) pairs.
top_users = sorted(todos_by_user.items(), 
                   key=lambda x: x[1], reverse=True)

# Get the maximum number of complete TODOs.
max_complete = top_users[0][1]

# Create a list of all users who have completed
# the maximum number of TODOs.
users = []
for user, num_complete in top_users:
    if num_complete < max_complete:
        break
    users.append(str(user))

max_users = " and ".join(users)

Да, ваша реализация лучше, но суть в том, что теперь вы можете манипулировать данными JSON как обычным объектом Python!

Я не знаю о вас, но когда я снова запускаю скрипт в интерактивном режиме, я получаю следующие результаты:

>>> s = "s" if len(users) > 1 else ""
>>> print(f"user{s} {max_users} completed {max_complete} TODOs")
users 5 and 10 completed 12 TODOs

Это круто и все, но вы здесь, чтобы узнать о JSON. Для окончательного задания вы создадите файл JSON, который содержит заполненные TODO для каждого из пользователей, выполнивших максимальное количество TODO.

Все, что вам нужно сделать, это отфильтровать todos и записать полученный список в файл. Ради оригинальности вы можете вызвать выходной файл filtered_data_file.json. Есть несколько способов, которыми вы могли бы пойти по этому поводу, но вот один:

# Define a function to filter out completed TODOs 
# of users with max completed TODOS.
def keep(todo):
    is_complete = todo["completed"]
    has_max_count = str(todo["userId"]) in users
    return is_complete and has_max_count

# Write filtered TODOs to file.
with open("filtered_data_file.json", "w") as data_file:
    filtered_todos = list(filter(keep, todos))
    json.dump(filtered_todos, data_file, indent=2)

Отлично, вы избавились от всех данных, которые вам не нужны, и сохранили полезные вещи в совершенно новый файл! Запустите скрипт еще раз и проверьте, filtered_data_file.json все ли работает. Он будет в том же каталоге, что и scratch.py при запуске.

Теперь, когда вы продвинулись так далеко, держу пари, что вы чувствуете себя довольно жарко, верно? Я склонен согласиться с вами, хотя. Пока что плавание прошло гладко, но вы можете захлестнуть люки на этом последнем отрезке.

Кодирование и декодирование пользовательских объектов Python

Что происходит, когда мы пытаемся сериализовать Elf класс из того приложения Dungeons & Dragons, над которым вы работаете?

class Elf:
    def __init__(self, level, ability_scores=None):
        self.level = level
        self.ability_scores = {
            "str": 11, "dex": 12, "con": 10,
            "int": 16, "wis": 14, "cha": 13
        } if ability_scores is None else ability_scores
        self.hp = 10 + self.ability_scores["con"]

Неудивительно, что Python жалуется, что Elf не сериализуем (что вы бы знали, если бы когда-нибудь попытались написать Elf иначе):

>>> elf = Elf(level=4)
>>> json.dumps(elf)
TypeError: Object of type 'Elf' is not JSON serializable

Хотя json модуль может обрабатывать большинство встроенных типов Python, он не понимает, как кодировать настраиваемые типы данных по умолчанию. Это все равно что пытаться втиснуть квадратный колышек в круглое отверстие.

Упрощение структур данных

Теперь вопрос в том, как бороться с более сложными структурами данных. Ну, вы можете попытаться кодировать и декодировать JSON вручную, но есть немного более умное решение, которое сэкономит вам немного работы. Вместо прямого перехода от пользовательского типа данных к JSON вы можете добавить промежуточный шаг.

Все, что вам нужно сделать, это представить ваши данные в терминах json уже понятных встроенных типов . По сути, вы переводите более сложный объект в более простое представление, которое json модуль затем переводит в JSON. Это как переходное свойство в математике: если A = B и B = C, то A = C.

Чтобы освоить это, вам понадобится сложный объект. Вы можете использовать любой пользовательский класс, который вам нравится, но в Python есть встроенный тип complex, который вызывается для представления комплексных чисел, и он по умолчанию не сериализуем. Итак, ради этих примеров, ваш сложный объект будет complex объектом:

>>> z = 3 + 8j
>>> type(z)
<class 'complex'>
>>> json.dumps(z)
TypeError: Object of type 'complex' is not JSON serializable

Откуда берутся комплексные числа? Видите ли, когда действительное число и воображаемое число очень любят друг друга, они складываются вместе, образуя число, которое (оправданно) называется сложным .

Хороший вопрос, который нужно задать себе при работе с пользовательскими типами: какой минимальный объем информации необходим для воссоздания этого объекта? В случае комплексных чисел вам нужно знать только действительные и мнимые части, к которым вы можете обращаться как к атрибутам complexобъекта:

>>> z.real
3.0
>>> z.imag
8.0

Передача одинаковых чисел в complex конструктор достаточна для выполнения __eq__ оператора сравнения:>>>

>>> complex(3, 8) == z
True

Разбиение пользовательских типов данных на их основные компоненты имеет решающее значение как для процессов сериализации, так и десериализации.

Кодирование пользовательских типов

Чтобы перевести пользовательский объект в JSON, все, что вам нужно сделать, это предоставить функцию кодирования для параметра метода  dump() default.  json модуль будет вызывать эту функцию на любых объектах, которые изначально не сериализованы. Вот простая функция декодирования, которую вы можете использовать на практике:

def encode_complex(z):
    if isinstance(z, complex):
        return (z.real, z.imag)
    else:
        type_name = z.__class__.__name__
        raise TypeError(f"Object of type '{type_name}' is not JSON serializable")

Обратите внимание, что вы должны поднять TypeError если вы не получите объект, который вы ожидали. Таким образом, вы избежите случайной сериализации любых Elf. Теперь вы можете попробовать кодировать сложные объекты!

>>> json.dumps(9 + 5j, default=encode_complex)
'[9.0, 5.0]'
>>> json.dumps(elf, default=encode_complex)
TypeError: Object of type 'Elf' is not JSON serializable

Почему мы закодировали комплексное число как tupleОтличный вопрос! Это, конечно, не был единственный выбор, и при этом это не обязательно лучший выбор. На самом деле, это не очень хорошее представление, если вы когда-нибудь захотите декодировать объект позже, как вы вскоре увидите.

Другой распространенный подход – создать подкласс стандарта JSONEncoder и переопределить его default() метод:

class ComplexEncoder(json.JSONEncoder):
    def default(self, z):
        if isinstance(z, complex):
            return (z.real, z.imag)
        else:
            return super().default(z)

Вместо того, чтобы поднимать TypeErrorсебя, вы можете просто позволить базовому классу справиться с этим. Вы можете использовать это либо непосредственно в dump()методе через clsпараметр, либо создав экземпляр кодировщика и вызвав его encode()метод:>>>

>>> json.dumps(2 + 5j, cls=ComplexEncoder)
'[2.0, 5.0]'

>>> encoder = ComplexEncoder()
>>> encoder.encode(3 + 6j)
'[3.0, 6.0]'

Расшифровка пользовательских типов

Хотя действительные и мнимые части комплексного числа абсолютно необходимы, на самом деле их недостаточно для воссоздания объекта. Вот что происходит, когда вы пытаетесь кодировать комплексное число с помощью ComplexEncoder а затем декодировать результат:

>>> complex_json = json.dumps(4 + 17j, cls=ComplexEncoder)
>>> json.loads(complex_json)
[4.0, 17.0]

Все, что вы получите, это список, и вам придется передать значения в complex конструктор, если вы захотите снова создать этот сложный объект. Вспомните нашу дискуссию о телепортации. Отсутствуют метаданные или информация о типе данных, которые вы кодируете.

Я полагаю, что вопрос, который вы действительно должны задать себе: каков минимальный объем информации, который необходим и достаточен для воссоздания этого объекта?

json модуль ожидает, что все пользовательские типы должны быть выражены как objects в стандарте JSON. Для разнообразия вы можете создать файл JSON на этот раз complex_data.json и добавить следующее object представляющее комплексное число:

{
    "__complex__": true,
    "real": 42,
    "imag": 36
}

Видите умный бит? Этот "__complex__" ключ – метаданные, о которых мы только что говорили. На самом деле не имеет значения, что это за значение. Чтобы заставить этот маленький взломать работать, все, что вам нужно сделать, это убедиться, что ключ существует:

def decode_complex(dct):
    if "__complex__" in dct:
        return complex(dct["real"], dct["imag"])
    return dct

Если "__complex__" нет в словаре, вы можете просто вернуть объект и позволить декодеру по умолчанию справиться с ним.

Каждый раз, когда load() метод пытается выполнить синтаксический анализ object, вам предоставляется возможность вмешаться до того, как декодер по умолчанию доберется до данных. Вы можете сделать это, передав функцию декодирования параметру object_hook.

Теперь то же, что и раньше:

>>> with open("complex_data.json") as complex_data:
...     data = complex_data.read()
...     z = json.loads(data, object_hook=decode_complex)
... 
>>> type(z)
<class 'complex'>

Хотя object_hook может показаться аналогом параметра dump() метода default, аналогия действительно начинается и заканчивается там.

Это не просто работает с одним объектом. Попробуйте вставить этот список комплексных чисел complex_data.json и снова запустить скрипт:

[
  {
    "__complex__":true,
    "real":42,
    "imag":36
  },
  {
    "__complex__":true,
    "real":64,
    "imag":11
  }
]

Если все пойдет хорошо, вы получите список complex объектов:

>>> with open("complex_data.json") as complex_data:
...     data = complex_data.read()
...     numbers = json.loads(data, object_hook=decode_complex)
... 
>>> numbers
[(42+36j), (64+11j)]

Вы также можете попробовать создать подкласс JSONDecoder и переопределить object_hook, но лучше по возможности придерживаться облегченного решения.

Все сделано!

Поздравляем, теперь вы можете использовать мощную силу JSON для любого и всех ваших бесчестный Python нуждается.

Хотя примеры, с которыми вы работали здесь, безусловно, надуманы и чрезмерно упрощены, они иллюстрируют рабочий процесс, который вы можете применить к более общим задачам:

  1. Импортируйте json пакет.
  2. Прочитайте данные с помощью load() или loads().
  3. Обработайте данные.
  4. Запишите измененные данные с помощью dump() или dumps().

То, что вы будете делать со своими данными после их загрузки в память, будет зависеть от вашего варианта использования. Как правило, ваша цель будет собирать данные из источника, извлекать полезную информацию и передавать эту информацию вместе или вести ее учет.


Совершенствуй знания каждый день у нас в Телеграм-каналах

Вопросы, реклама — VK | Telegram

Модуль json | Python 3 для начинающих и чайников

JSON (JavaScript Object Notation) — простой формат обмена данными, основанный на подмножестве синтаксиса JavaScript. Модуль json позволяет кодировать и декодировать данные в удобном формате.

Кодирование основных объектов Python:

>>> import json
>>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
'["foo", {"bar": ["baz", null, 1.0, 2]}]'
>>> print(json.dumps("\"foo\bar"))
"\"foo\bar"
>>> print(json.dumps('\u1234'))
"\u1234"
>>> print(json.dumps('\\'))
"\\"
>>> print(json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True))
{"a": 0, "b": 0, "c": 0}

Компактное кодирование:

>>> import json
>>> json.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',', ':'))
'[1,2,3,{"4":5,"6":7}]'

Красивый вывод:

>>> import json
>>> print(json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4))
{
    "4": 5,
    "6": 7
}

Декодирование (парсинг) JSON:

>>> import json
>>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
['foo', {'bar': ['baz', None, 1.0, 2]}]
>>> json.loads('"\\"foo\\bar"')
'"foo\x08ar'

Основы

json.dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw) — сериализует obj как форматированный JSON поток в fp.

Если skipkeys = True, то ключи словаря не базового типа (str, unicode, int, long, float, bool, None) будут проигнорированы, вместо того, чтобы вызывать исключение TypeError.

Если ensure_ascii = True, все не-ASCII символы в выводе будут экранированы последовательностями \uXXXX, и результатом будет строка, содержащая только ASCII символы. Если ensure_ascii = False, строки запишутся как есть.

Если check_circular = False, то проверка циклических ссылок будет пропущена, а такие ссылки будут вызывать OverflowError.

Если allow_nan = False, при попытке сериализовать значение с запятой, выходящее за допустимые пределы, будет вызываться ValueError (nan, inf, -inf) в строгом соответствии со спецификацией JSON, вместо того, чтобы использовать эквиваленты из JavaScript (NaN, Infinity, -Infinity).

Если indent является неотрицательным числом, то массивы и объекты в JSON будут выводиться с этим уровнем отступа. Если уровень отступа 0, отрицательный или «», то вместо этого будут просто использоваться новые строки. Значение по умолчанию None отражает наиболее компактное представление. Если indent — строка, то она и будет использоваться в качестве отступа.

Если sort_keys = True, то ключи выводимого словаря будут отсортированы.

json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw) — сериализует obj в строку JSON-формата.

Аргументы имеют то же значение, что и для dump().

Ключи в парах ключ/значение в JSON всегда являются строками. Когда словарь конвертируется в JSON, все ключи словаря преобразовываются в строки. В результате этого, если словарь сначала преобразовать в JSON, а потом обратно в словарь, то можно не получить словарь, идентичный исходному. Другими словами, loads(dumps(x)) != x, если x имеет нестроковые ключи.

json.load(fp, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw) — десериализует JSON из fp.

object_hook — опциональная функция, которая применяется к результату декодирования объекта (dict). Использоваться будет значение, возвращаемое этой функцией, а не полученный словарь.

object_pairs_hook — опциональная функция, которая применяется к результату декодирования объекта с определённой последовательностью пар ключ/значение. Будет использован результат, возвращаемый функцией, вместо исходного словаря. Если задан так же object_hook, то приоритет отдаётся object_pairs_hook.

parse_float, если определён, будет вызван для каждого значения JSON с плавающей точкой. По умолчанию, это эквивалентно float(num_str).

parse_int, если определён, будет вызван для строки JSON с числовым значением. По умолчанию эквивалентно int(num_str).

parse_constant, если определён, будет вызван для следующих строк: «-Infinity», «Infinity», «NaN». Может быть использовано для возбуждения исключений при обнаружении ошибочных чисел JSON.

Если не удастся десериализовать JSON, будет возбуждено исключение ValueError.

json.loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw) — десериализует s (экземпляр str, содержащий документ JSON) в объект Python.

Остальные аргументы аналогичны аргументам в load().

Кодировщики и декодировщики

Класс json.JSONDecoder(object_hook=None, parse_float=None, parse_int=None, parse_constant=None, strict=True, object_pairs_hook=None) — простой декодер JSON.

Выполняет следующие преобразования при декодировании:

JSONPython
objectdict
arraylist
stringstr
number (int)int
number (real)float
trueTrue
falseFalse
nullNone

Он также понимает NaN, Infinity, и -Infinity как соответствующие значения float, которые находятся за пределами спецификации JSON.

Класс json.JSONEncoder(skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)

Расширяемый кодировщик JSON для структур данных Python. Поддерживает следующие объекты и типы данных по умолчанию:

PythonJSON
dictobject
list, tuplearray
strstring
int, floatnumber
Truetrue
Falsefalse
Nonenull

Чтение и запись JSON в файл в Python

Введение

В этой статье мы будем анализировать, читать и записывать данные JSON в файл на Python.

За последние 5-10 лет формат JSON был одним из, если не самым, популярным способом сериализации данных. Особенно в мире веб-разработки вы, вероятно, столкнетесь с JSON через один из многих REST API, конфигурацию приложения или даже простое хранилище данных.

Учитывая его распространенность и влияние на программирование, на каком-то этапе разработки вы, вероятно, захотите научиться читать JSON из файла или записывать JSON в файл.Обе эти задачи довольно легко выполнить с помощью Python, как вы увидите в следующих нескольких разделах.

Запись JSON в файл

Самый простой способ записать ваши данные в формате JSON в файл с помощью Python — использовать хранилище данных в объекте dict , который может содержать другие вложенные dict s, массивы, логические или другие примитивные типы, такие как целые числа. и струны. Вы можете найти более подробный список поддерживаемых типов данных здесь.

Встроенный пакет json имеет волшебный код, который преобразует ваш объект Python dict в сериализованную строку JSON.

  импорт json

данные = {}
данные ['люди'] = []
data ['люди']. append ({
    'name': 'Скотт',
    'сайт': 'stackabuse.com',
    'from': 'Небраска'
})
data ['люди']. append ({
    'name': 'Ларри',
    'website': 'google.com',
    'from': 'Мичиган'
})
data ['люди']. append ({
    'name': 'Тим',
    'website': 'apple.com',
    'from': 'Алабама'
})

с open ('data.txt', 'w') в качестве файла вывода:
    json.dump (данные, выходной файл)
  

После импорта библиотеки json мы создаем несколько простых данных для записи в наш файл.Важная часть приходит в конце, когда мы используем оператор with для открытия нашего конечного файла, а затем используем json.dump для записи объекта data в файл Outfile .

Любой файловый объект может быть передан второму аргументу, даже если это не настоящий файл. Хорошим примером этого может быть сокет, который можно открывать, закрывать и записывать в него, как в файл. Поскольку JSON популярен в Интернете, это еще один вариант использования, с которым вы можете столкнуться.

Небольшая разновидность метода json.dump , о котором стоит упомянуть, — это json.dumps, который возвращает фактическую строку JSON вместо того, чтобы отправлять ее непосредственно в объект с возможностью записи. Это может дать вам больше контроля, если вам нужно внести некоторые изменения в строку JSON (например, зашифровать ее).

Чтение JSON из файла

С другой стороны, чтение данных JSON из файла так же просто, как их запись в файл. Снова используя тот же пакет json , мы можем извлечь и проанализировать строку JSON непосредственно из файлового объекта.В следующем примере мы делаем именно это, а затем распечатываем полученные данные:

  импорт json

с open ('data.txt') как json_file:
    данные = json.load (json_file)
    для p в данных ['люди']:
        print ('Имя:' + p ['имя'])
        print ('Веб-сайт:' + p ['веб-сайт'])
        print ('От:' + p ['от'])
        Распечатать('')
  

Здесь следует обратить внимание на

json.load. Он считывает строку из файла, анализирует данные JSON, заполняет данными Python dict и возвращает их вам.

Так же, как json.dump , json.load имеет альтернативный метод, который позволяет вам работать со строками напрямую, поскольку во многих случаях у вас, вероятно, не будет файлового объекта, содержащего ваш JSON. Как вы, наверное, догадались, это метод json.loads. Рассмотрим случай, когда вы вызываете конечную точку REST GET, которая возвращает JSON. Эти данные поступают к вам в виде строки, которую вы затем можете напрямую передать в json.loads .

Опции

При сериализации данных в JSON с помощью Python результат будет в стандартном формате и не очень удобочитаемым, так как пробелы удалены.Хотя это идеальное поведение для большинства случаев, иногда вам может потребоваться внести небольшие изменения, например добавить пробелы, чтобы сделать его удобочитаемым. И json.dump , и json.load предоставляют несколько вариантов для большей гибкости, некоторые из которых будут описаны здесь.

Красочная печать

Сделать JSON удобочитаемым (он же «красивый») так же просто, как передать целочисленное значение для параметра indent :

  >>> импорт json
>>> data = {'people': [{'name': 'Scott', 'website': 'stackabuse.com ',' from ':' Небраска '}]}
>>> json.dumps (данные, отступ = 4)
{
    "люди": [
        {
            "сайт": "stackabuse.com",
            "from": "Небраска",
            "name": "Скотт"
        }
    ]
}
  

На самом деле это очень полезно, поскольку вам часто придется читать данные JSON во время разработки. Другой вариант — использовать инструмент командной строки json.tool . Поэтому, если вы просто хотите распечатать JSON в командной строке, вы можете сделать что-то вроде этого:

  $ echo '{"people": [{"name": "Скотт", "website": "stackabuse.com "," from ":" Небраска "}]} '| python -m json.tool
{
    "люди": [
        {
            "name": "Скотт",
            "сайт": "stackabuse.com"
            "from": "Небраска",
        }
    ]
}
  
Сортировка

В JSON объект определяется как:

Объект — это неупорядоченный набор пар имя / значение.

Итак, стандарт гласит, что порядок ключей не гарантируется, но возможно, что он вам может понадобиться для ваших внутренних целей.Для упорядочивания вы можете передать True параметру sort_keys при использовании json.dump или json.dumps .

  >>> импорт json
>>> data = {'people': [{'name': 'Scott', 'website': 'stackabuse.com', 'from': 'Nebraska'}]}
>>> json.dumps (данные, sort_keys = True, indent = 4)
{
    "люди": [
        {
            "from": "Небраска",
            "name": "Скотт",
            "сайт": "stackabuse.com"
        }
    ]
}
  
Текст ASCII

По умолчанию json.dump гарантирует, что весь ваш текст в данном словаре Python имеет кодировку ASCII. Если присутствуют символы, отличные от ASCII, они автоматически экранируются, как показано в следующем примере:

  >>> импорт json
>>> data = {'item': 'Пиво', 'cost': '4,00 фунта стерлингов'}
>>> jstr = json.dumps (данные, отступ = 4)
>>> печать (jstr)
{
    "item": "Пиво",
    "cost": "\ u00a34.00"
}
  

Это не всегда приемлемо, и во многих случаях вы можете не трогать символы Unicode.Для этого установите для параметра sure_ascii значение False .

  >>> jstr = json.dumps (data, sure_ascii = False, indent = 4)
>>> печать (jstr)
{
    "item": "Пиво",
    "стоимость": "4,00 фунта стерлингов"
}
  

Заключение

В этой статье мы познакомили вас с методами json.dump , json.dumps , json.load и json.loads , которые помогают в сериализации и десериализации строк JSON.

Поскольку JSON стал одним из самых популярных способов сериализации структурированных данных, вам, вероятно, придется довольно часто взаимодействовать с ним, особенно при работе с веб-приложениями.Модуль Python json — отличный способ начать работу, хотя вы, вероятно, обнаружите, что

.

Чтение, запись, анализ JSON (с примерами)

JSON ( J ava S cript O bject N otation) — популярный формат данных, используемый для представления структурированных данных. Обычно данные между сервером и веб-приложением передаются и принимаются в формате JSON.

В Python JSON существует в виде строки. Например:

  p = '{"name": "Bob", "languages": ["Python", "Java"]}'
  

Также часто объект JSON хранится в файле.


Импорт модуля json

Для работы с JSON (строкой или файлом, содержащим объект JSON) вы можете использовать модуль Python json . Вам необходимо импортировать модуль, прежде чем вы сможете его использовать.

  импорт JSON  

Разобрать JSON в Python

Модуль json упрощает синтаксический анализ строк и файлов JSON, содержащих объект JSON.


Пример 1: Python JSON для определения

Вы можете проанализировать строку JSON, используя json.load () метод. Метод возвращает словарь.

  импорт json

person = '{"name": "Bob", "languages": ["English", "Fench"]}'
person_dict = json.loads (человек)

# Вывод: {'name': 'Bob', 'languages': ['English', 'Fench']}
печать (person_dict)

# Вывод: ['английский', 'французский']
print (person_dict ['языки'])  

Здесь человек — строка JSON, а person_dict — словарь.


Пример 2: Python прочитал файл JSON

Вы можете использовать json.load () для чтения файла, содержащего объект JSON.

Предположим, у вас есть файл с именем person.json , который содержит объект JSON.

 
{"name": "Боб",
"languages": ["английский", "фенч"]
}
  

Вот как можно разобрать этот файл:

 
импортировать json

с open ('path_to_file / person.json') как f:
  data = json.load (f)

# Вывод: {'name': 'Bob', 'languages': ['English', 'Fench']}
печать (данные)
  

Здесь мы использовали функцию open () для чтения файла json.Затем файл анализируется с использованием метода json.load () , который дает нам словарь с именем data .

Если вы не знаете, как читать и записывать файлы в Python, мы рекомендуем вам проверить ввод-вывод файлов Python.


Python Преобразовать в строку JSON

Вы можете преобразовать словарь в строку JSON с помощью метода json.dumps () .


Пример 3: преобразование dict в JSON

 
импортировать json

person_dict = {'name': 'Боб',
'возраст': 12,
'children': нет
}
person_json = json.свалки (person_dict)

# Вывод: {"name": "Bob", "age": 12, "children": null}
печать (person_json)
  

Вот таблица, в которой показаны объекты Python и их эквивалентное преобразование в JSON.

Python Эквивалент JSON
дикт объект
список , кортеж массив
ул. строка
внутр , с плавающей запятой , внутр номер
Правда правда
Ложь ложь
Нет null

Запись JSON в файл

Чтобы записать JSON в файл на Python, мы можем использовать json.dump () метод.


Пример 4: Запись JSON в файл

 
импортировать json

person_dict = {"name": "Боб",
«языки»: [«английский», «фенч»],
"женат": Верно,
«возраст»: 32
}

с open ('person.txt', 'w') как json_file:
  json.dump (person_dict, json_file)
  

В приведенной выше программе мы открыли файл с именем person.txt в режиме записи с использованием 'w' . Если файл еще не существует, он будет создан. Затем json.dump () преобразует person_dict в строку JSON, которая будет сохранена в файле person.txt .

При запуске программы будет создан файл person.txt . Внутри файла есть следующий текст.

  {"name": "Bob", "languages": ["English", "Fench"], "женат": true, "age": 32}  

Python красивая печать JSON

Для анализа и отладки данных JSON нам может потребоваться распечатать их в более удобочитаемом формате.Это можно сделать, передав дополнительные параметры indent и sort_keys в метод json.dumps () и json.dump () .


Пример 5: Python довольно печатает JSON

 
импортировать json

person_string = '{"name": "Боб", "languages": "английский", "numbers": [2, 1.6, null]}'

# Получение словаря
person_dict = json.loads (person_string)

# Довольно Печать строки JSON назад
print (json.dumps (person_dict, indent = 4, sort_keys = True))
  

Когда вы запустите программу, на выходе будет:

 
{
    "languages": "английский",
    "name": "Боб",
    "числа": [
        2,
        1.6,
        значение NULL
    ]
}
  

В приведенной выше программе мы использовали 4 пробелов для отступов. И ключи отсортированы в порядке возрастания.

Кстати, значение по умолчанию , отступ Нет . И значение по умолчанию sort_keys False .


Рекомендуемая литература:

  • Python JSON в CSV и наоборот
  • Python XML в JSON и наоборот
  • Python simplejson

.

json — кодировщик и декодер JSON — документация Python 3.8.6

Исходный код: Lib / json / __ init__.py


JSON (нотация объектов JavaScript), определенная
RFC 7159 (который устарел RFC 4627 ) и
ECMA-404,
это легкий формат обмена данными, вдохновленный
Синтаксис литерала объекта JavaScript
(хотя это не строгое подмножество JavaScript).

json предоставляет API, знакомый пользователям стандартной библиотеки
marshal и pickle модулей.

Кодирование базовой иерархии объектов Python:

 >>> импортировать json
>>> json.dumps (['foo', {'bar': ('baz', None, 1.0, 2)}])
'["foo", {"bar": ["baz", null, 1.0, 2]}]'
>>> print (json.dumps ("\" foo \ bar "))
"\" фу \ бар "
>>> печать (json.dumps ('\ u1234'))
"\ u1234"
>>> печать (json.dumps ('\\'))
"\\"
>>> print (json.dumps ({"c": 0, "b": 0, "a": 0}, sort_keys = True))
{"a": 0, "b": 0, "c": 0}
>>> из io import StringIO
>>> io = StringIO ()
>>> json.дамп (['потоковый API'], io)
>>> io.getvalue ()
'["потоковый API"]'
 

Компактное кодирование:

 >>> импортировать json
>>> json.dumps ([1, 2, 3, {'4': 5, '6': 7}], separators = (',', ':'))
'[1,2,3, {"4": 5, "6": 7}]'
 

Довольно полиграфический:

 >>> импортировать json
>>> print (json.dumps ({'4': 5, '6': 7}, sort_keys = True, indent = 4))
{
    «4»: 5,
    «6»: 7
}
 

Расшифровка JSON:

 >>> импортировать json
>>> json.load ('["foo", {"bar": ["baz", null, 1.0, 2]}]')
['foo', {'bar': ['baz', None, 1.0, 2]}]
>>> json.loads ('"\\" foo \\ bar "')
'"foo \ x08ar'
>>> из io import StringIO
>>> io = StringIO ('["потоковый API"]')
>>> json.load (io)
['потоковый API']
 

Специализированное декодирование объекта JSON:

 >>> импортировать json
>>> def as_complex (dct):
... если '__complex__' в dct:
... вернуть комплекс (dct ['real'], dct ['imag'])
... вернуть dct
...
>>> json.loads ('{"__ complex__": true, "real": 1, "imag": 2}',
... object_hook = as_complex)
(1 + 2j)
>>> импортировать десятичный
>>> json.loads ('1.1', parse_float = decimal.Decimal)
Десятичный ('1.1')
 

Расширение JSONEncoder :

 >>> импортировать json
>>> класс ComplexEncoder (json.JSONEncoder):
... def default (self, obj):
... если isinstance (obj, complex):
... вернуть [obj.real, obj.imag]
... # Разрешить методу по умолчанию базового класса вызвать TypeError
... вернуть json.JSONEncoder.default (self, obj)
...
>>> json.dumps (2 + 1j, cls = ComplexEncoder)
'[2.0, 1.0]'
>>> ComplexEncoder (). Кодировать (2 + 1j)
'[2.0, 1.0]'
>>> список (ComplexEncoder (). iterencode (2 + 1j))
['[2.0', ', 1.0', ']']
 

Использование json.tool из оболочки для проверки и красивой печати:

 $ echo '{"json": "obj"}' | python -m json.tool
{
    "json": "obj"
}
$ echo '{1.2: 3.4}' | python -m json.tool
Ожидание имени свойства, заключенного в двойные кавычки: строка 1 столбец 2 (символ 1)
 

Для получения подробной документации см. Интерфейс командной строки.

Примечание

JSON — это подмножество YAML 1.2. JSON, созданный
настройки этого модуля по умолчанию (в частности, разделители по умолчанию
value) также является подмножеством YAML 1.0 и 1.1. Таким образом, этот модуль также может быть
используется как сериализатор YAML.

Примечание

Кодеры и декодеры этого модуля сохраняют порядок ввода и вывода на
дефолт. Порядок теряется только в том случае, если нижележащие контейнеры неупорядочены.

До Python 3.7 заказ dict не гарантировался, поэтому
входы и выходы обычно скремблировались, если
коллекций.OrderedDict был специально запрошен. Запуск
с Python 3.7 обычный

.

Работа с данными JSON в Python — Настоящий Python