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 согласно с весьма интуитивной конверсией.
Python | JSON |
dict | object |
list, tuple | array |
str | string |
int, long, float | number |
True | true |
False | false |
None | null |
Пример сериализации 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.
Как и сериализация, есть простая таблица конверсии для десериализации, так что вы можете иметь представление о том, как все выглядит.
JSON | Python |
object | dict |
array | list |
string | str |
number (int) | int |
number (real) | float |
true | True |
false | False |
null | None |
Технически, эта конверсия не является идеальной инверсией таблицы сериализации. По сути, это значит что если вы кодируете объект сейчас, а затем декодируете его в будущем, вы можете не получить тот же объект назад. Я представляю это как своего рода телепортацию: мои молекулы распадаются в точке А и собираются в точке Б. Буду ли я тем же самым человеком?
В реальности, это как попросить одного друга перевести что-нибудь на японский, а потом попросить другого друга перевести это обратно на русский. В любом случае, самым простым примером будет кодировать кортеж и получить назад список после декодирования, вот так:
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.
Хотя примеры, с которыми вы работали, безусловно, оригинальные и чрезмерно упрощены, они демонстрируют рабочий процесс, который вы можете применить к более общим задачам:
- Импорт модуля json
- Чтение данных с load() или loads()
- Обработка данных
- Запись измененных данных при помощи 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:
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float | number |
True | true |
False | false |
None | null |
Таблица конвертации JSON в данные Python:
JSON | Python |
---|---|
object | dict |
array | list |
string | str |
number (int) | int |
number (real) | float |
true | True |
false | False |
null | None |
Ограничение по типам данных
В формат 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:
Python | JSON |
---|---|
dict | Object |
list | Array |
tuple | Array |
str | String |
int | Number |
float | Number |
True | true |
False | false |
None | null |
Конвертируйте объект 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.
При декодировании выполняет следующие преобразования:
JSON | Python |
---|---|
object | dict |
array | list |
string | str |
number (int) | int |
number (real) | float |
true | True |
false | False |
null | None |
Он также понимает 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.
Поддерживает следующие типы данных и объекты по умолчанию:
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float | number |
True | true |
False | false |
None | null |
Для того, чтобы можно было распознавать и другие объекты, подкласс должен выполнить метод 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 в соответствии с довольно интуитивным преобразованием.
Python | JSON |
---|---|
dict | object |
list , tuple | array |
str | string |
int , long ,float | number |
True | true |
False | false |
None | null |
Простой пример сериализации
Представьте, что вы работаете с объектом 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.
Как и в случае с сериализацией, для десериализации существует простая таблица преобразования, хотя вы, вероятно, уже догадались, как она выглядит.
JSON | Python |
---|---|
object | dict |
array | list |
string | str |
number (целый) | int |
number (действительный) | float |
true | True |
false | False |
null | None |
Технически, это преобразование не является совершенной противоположностью таблице сериализации. По сути, это означает, что если вы кодируете объект сейчас, а потом декодируете его позже, вы не сможете получить точно такой же объект обратно. Я полагаю, это немного похоже на телепортацию: разбейте мои молекулы здесь и соедините их там. Я все еще тот же человек?
В действительности, это скорее похоже на то, как один друг переводит что-то на японский, а другой – обратно на русский. В любом случае, простейшим примером будет кодирование 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 нуждается.
Хотя примеры, с которыми вы работали здесь, безусловно, надуманы и чрезмерно упрощены, они иллюстрируют рабочий процесс, который вы можете применить к более общим задачам:
- Импортируйте
json
пакет. - Прочитайте данные с помощью
load()
илиloads()
. - Обработайте данные.
- Запишите измененные данные с помощью
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.
Выполняет следующие преобразования при декодировании:
JSON | Python |
---|---|
object | dict |
array | list |
string | str |
number (int) | int |
number (real) | float |
true | True |
false | False |
null | None |
Он также понимает 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. Поддерживает следующие объекты и типы данных по умолчанию:
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float | number |
True | true |
False | false |
None | null |
Чтение и запись 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
Смотреть сейчас Это руководство содержит соответствующий видеокурс, созданный командой Real Python. Посмотрите его вместе с письменным руководством, чтобы углубить свое понимание: Работа с данными JSON в Python
С момента своего создания JSON быстро стал де-факто стандартом для обмена информацией. Скорее всего, вы здесь, потому что вам нужно передать некоторые данные отсюда туда. Возможно, вы собираете информацию через API или храните данные в базе данных документов.Так или иначе, вы по уши в JSON, и у вас есть выход на Python.
К счастью, это довольно распространенная задача, и, как и в случае с большинством обычных задач, Python делает ее почти отвратительно простой. Не бойтесь, коллеги-питонисты и питонисты. Это будет проще простого!
Итак, мы используем JSON для хранения и обмена данными?
Ага, ты понял! Это не более чем стандартизированный формат, который сообщество использует для передачи данных. Имейте в виду, что JSON — не единственный формат, доступный для такого рода работы, но XML и YAML, вероятно, единственные другие, о которых стоит упомянуть одновременно.
A (Очень) Краткая история JSON
Неудивительно, что сценарий J ava S cript O bject N был вдохновлен подмножеством языка программирования JavaScript, имеющим дело с синтаксисом объектных литералов. У них есть отличный веб-сайт, который все объясняет. Но не волнуйтесь: JSON уже давно стал независимым от языка и существует как собственный стандарт, так что мы, к счастью, можем избежать JavaScript для этого обсуждения.
В конце концов, сообщество в целом приняло JSON, потому что его легко создавать и понимать как людям, так и машинам.
Смотрите, это JSON!
Будьте готовы. Я собираюсь показать вам JSON из реальной жизни — точно такой, какой вы бы видели на природе. Ничего страшного: JSON должен быть доступен для чтения всем, кто использует язык в стиле C, а Python — это язык в стиле C… так что это вы!
{
"firstName": "Джейн",
"lastName": "Лань",
«хобби»: [«бег», «прыжки с парашютом», «пение»],
«возраст»: 35,
"дети": [
{
"firstName": "Алиса",
«возраст»: 6
},
{
"firstName": "Боб",
«возраст»: 8
}
]
}
Как видите, JSON поддерживает примитивные типы, такие как строки и числа, а также вложенные списки и объекты.
Подождите, это похоже на словарь Python!
Я точно знаю? На данный момент это довольно универсальная объектная нотация, но я не думаю, что UON так хорошо соскальзывает с языка. Не стесняйтесь обсуждать альтернативы в комментариях.
Уф! Вы пережили свою первую встречу с каким-то диким JSON. Теперь вам просто нужно научиться приручать его.
Python изначально поддерживает JSON!
Python поставляется со встроенным пакетом json
для кодирования и декодирования данных JSON.
Просто поместите этого человечка в начало файла:
Немного словаря
Процесс кодирования JSON обычно называется сериализацией . Этот термин относится к преобразованию данных в серию байтов (следовательно, серийный ) для хранения или передачи по сети. Вы также можете слышать термин marshaling , но это
.