{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "### Что такое JSON и зачем он нужен?\n", "\n", "Аббревиатура `JSON` расшифровывается как `JavaScript Object Notation` или, в вольном переводе, система обозначения (или записи) объектов JavaScript. \n", "\n", "Несмотря на то, что `JSON` является подмножеством языка программирования JavaScript, сейчас это общепризнанный формат обмена данными, и многие языки программирования, включая Python, содержат эффективные инструменты для работы с этим форматом.\n", "\n", "Важно! Итак, JSON — это простой, структурированный, основанный на использовании текста формат обмена данными.\n", "\n", "Когда мы говорим об обмене данными, то чаще всего имеем в виду передачу данных по компьютерным сетям, например пересылку данных от сервера к браузеру. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Инструменты для работы с JSON\n", "\n", "Для работы с данными в формате `JSON` в Python используется библиотека `json`, которую необходимо будет загрузить в начале работы. Также нам может быть полезен модуль `pprint` (именно так, с двумя \"р\" в начале) и встроенная в него функция `pprint`, с помощью которой можно красиво выводить на экран структурированные данные." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import json \n", "from pprint import pprint " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Как выглядит JSON?\n", "\n", "Информация в формате `JSON` представляет собой (в закодированном виде) одну из двух структур:\n", "\n", "* набор пар \"ключ-значение\", причём ключ — это всегда строковая величина; в Python такая структура преобразуется в словарь;\n", "* упорядоченный набор значений; при чтении JSON в Python эта структура будет преобразована в список.\n", "\n", "Формат JSON допускает неограниченное количество вложений этих структур друг в друга. \n", "\n", "Все упражнения будем выполнять на примере файла, содержащего информацию об ингредиентах блюд, относящихся к кухням разных народов. \n", "\n", "### Смотрим на данные\n", "\n", "Чтобы перевести данные из формата `JSON` в формат, который можно обрабатывать на Python, необходимо выполнить процедуру, которая называется `десериализация` (иными словами, декодирование данных). Обратный процесс, связанный с переводом структур данных Python в формат `JSON`, называется `сериализация`.\n", "\n", "Для выполнения десериализации мы воспользуемся методом `load` модуля `json`. В качестве параметра укажем ссылку на файл:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "with open('data/recipes.json') as f:\n", " recipes = json.load(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Чтобы разобраться в структуре данных, давайте выведем их на экран с помощью функции `pprint`. Будьте готовы к тому, что данных в наборе много, поэтому в ячейке появится несколько сот строк. Нам не нужно будет просматривать все строки. Главное — понять общую структуру объекта `recipes`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "#pprint(recipes)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```JSON\n", "[{'cuisine': 'greek',\n", " 'id': 10259,\n", " 'ingredients': ['romaine lettuce',\n", " 'black olives',\n", " 'grape tomatoes',\n", " 'garlic',\n", " 'pepper',\n", " 'purple onion',\n", " 'seasoning',\n", " 'garbanzo beans',\n", " 'feta cheese crumbles']},\n", " {'cuisine': 'southern_us',\n", " 'id': 25693,\n", " 'ingredients': ['plain flour',\n", " 'ground pepper',\n", " 'salt',\n", " 'tomatoes',\n", " 'ground black pepper',\n", " 'thyme',\n", " 'eggs',\n", " 'green tomatoes',\n", " 'yellow corn meal',\n", " 'milk',\n", " 'vegetable oil']},\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Итак, мы видим, что рецепт каждого блюда описан в виде словаря, состоящего из трёх пар \"ключ-значение\". Ключ `cuisine` обозначает принадлежность блюда к определённой кухне, `id` — это уникальный идентификационный номер блюда, а ключ `ingredients` содержит перечень продуктов, входящих в состав блюда." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Извлекаем единичные данные\n", "\n", "После того как мы провели десериализацию данных из JSON-файла, мы можем работать с полученным объектом, как с обычным словарём, или, как в случае с нашими данными, списком. Единственное отличие этой работы от манипуляций с привычными нам списками и словарями заключается в том, что данных теперь больше и они помещены внутрь структуры с большим количеством уровней вложенности. Тем не менее общие приёмы работы остаются стандартными.\n", "\n", "Давайте выясним некоторые детали о блюде, которое записано первым в списке. Например, чтобы узнать `ID` этого блюда, мы можем использовать такой код:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10259" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "recipes[0]['id']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В данном случае сначала мы извлекаем из списка первый элемент (индекс 0). Поскольку каждый элемент списка является словарём, для получения нужной информации о конкретном блюде нам нужно указать ключ словаря. `ID` блюда доступно по ключу `'id'`, и мы указываем этот ключ в отдельной паре квадратных скобок." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Для получения списка ингредиентов первого блюда в списке мы можем использовать тот же код, заменив в нём ключ `'id'` на `'ingredients'`:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['romaine lettuce',\n", " 'black olives',\n", " 'grape tomatoes',\n", " 'garlic',\n", " 'pepper',\n", " 'purple onion',\n", " 'seasoning',\n", " 'garbanzo beans',\n", " 'feta cheese crumbles']" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "recipes[0]['ingredients']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ещё один пример касается извлечения информации о конкретном блюде. Давайте попробуем найти информацию о том, к какой кухне относится блюдо с `id = 13121`. Сложность задачи заключается в том, что все `id` хранятся в словарях, которые являются элементами списка. Для получения данных о нужном блюде нам придётся перебрать все элементы списка, проверить их `id`, и при обнаружении совпадения извлечь нужную информацию:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "thai\n" ] } ], "source": [ "for recipe in recipes: # начинаем перебор всех рецептов\n", " if recipe['id'] == 13121: # если id текущего рецепта равен искомому\n", " print(recipe['cuisine']) # выводим на экран кухню, к которой относится блюдо\n", " break # и прерываем цикл, т.к. нужное блюдо уже найдено" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Теперь мы можем обращаться к словарю food по ключам и получать информацию о количестве рецептов, включающих тот или иной ингредиент:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.3" } }, "nbformat": 4, "nbformat_minor": 4 }