В статье рассматриваются основные подходы для работы с JSON в языке Go. Большое внимание уделено определениям из документации, а также конкретным примерам.
Введение в JSON
JSON (JavaScript Object Notation) – это легкий формат обмена данными, основанный на синтаксисе объектов JavaScript. Он широко используется для передачи информации между клиентом и сервером в сетевых приложениях.
JSON представляет данные в виде пар «ключ-значение» и может содержать массивы, числа, строки, логические значения и null. Он обеспечивает простоту чтения и записи для людей, а также легкость разбора и генерации для компьютеров.
Чтение JSON
Десериализация (чтение JSON) – это процесс преобразования данных из формата JSON в объекты Go. Для этих целей используется пакет encoding/json, который входит в стандартную библиотеку языка. Основная функция для чтения Unmarshal считывает JSON-данные и сохраняет результат в значении, на которое указывает заданная переменная. Если же она представляет собой nil или не является указателем, то функция вернет InvalidUnmarshalError.
Общая сигнатура: func Unmarshal(data []byte, v any) error
Рассмотрим применение функции Unmarshal на конкретном примере:
В результате работы программы будет выведено "{Петя 18 программист}".
- Функция Unmarshal обладает интересной особенностью – она считывает только поля, соответствующие объявленным типам. Такое поведение используется для выборки определенных данных из большого JSON-файла.
В следующем примере будут заполнены только поля Name и Age, а Job останется проигнорированным. Вывод будет следующий: "{Витя 20 }".
👨💻 Библиотека Go разработчика
Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека Go разработчика»
🧩 Библиотека задач по Go
Интересные задачи по Go для практики можно найти на нашем телеграм-канале «Библиотека задач по Go»
🎓 Библиотека Go для собеса
Подтянуть свои знания по Go вы можете на нашем телеграм-канале «Библиотека Go для собеса»
Запись JSON
Сериализация (запись JSON) – это процесс преобразования объекта в формат, который можно сохранить или передать по сети. Для этого в Go используется функция Marshal() из ранее рассмотренного пакета encoding/json. Она возвращает два значения – срез байт и ошибку.
Её сигнатура имеет следующий вид: func Marshal(v any) ([]byte, error)
Стоит учитывать, что записаны могут быть только структуры данных, представимые в виде корректного формата JSON.
- Для кодировки типа map он должен иметь вид map[string]T, где T – любой тип, поддерживаемый пакетом encoding/json.
- Циклические структуры данных могут привести к попаданию функции Marshal в бесконечный цикл, поэтому не поддерживаются для преобразования.
- Для кодирования указателей необходимо представить их в виде значений, на которые они указывают. В случае nil-указателей это будет nil.
- Функции, каналы и тип complex не поддерживаются.
Потоковые кодировщики и декодеры
Интерфейсы Reader и Writer
В Go существуют два основных интерфейса из пакета io стандартной библиотеки, io.Reader и io.Writer. Они широко используются для ввода/вывода данных, при работе с файлами, сетевыми соединениями и другими объектами, поддерживающими операции чтения и записи.
Интерфейс io.Reader определяет метод Read, который принимает в качестве параметра буфер для чтения, а возвращает количество байт, прочитанных из источника, и ошибку. При завершении потока данных io.Reader возвращает ошибку io.EOF (конец файла).
Интерфейс io.Writer определяет метод Write, который принимает в качестве параметра буфер для записи данных, а возвращает количество байт, записанных в целевой объект, и ошибку.
При желании каждый разработчик может написать собственные интерфейсы Reader и Writer, руководствуясь соглашениями языка.
Кодировщик json.Encoder
Структура json.Encoder предназначена для кодирования JSON-данных и их последующей записи в выходной поток Writer.
Так выглядит сигнатура функции для создания кодировщика: func NewEncoder(w io.Writer) *Encoder
Декодер json.Decoder
Структура json.Decoder позволяет декодировать данные JSON из интерфейса Reader. К примеру, из файла, буфера или сетевого соединения. Decoder также обеспечивает возможность контроля синтаксических ошибок и обработки потока JSON-данных в режиме реального времени.
Сигнатура для создания декодера: func NewDecoder(r io.Reader) *Decoder
Рассмотрим пример использования этой функции.
На экран будет выведено: Иван 10
Тип NullString
В Go есть специальный тип NullString для работы с пустыми или отсутствующими значениями JSON-данных. Он позволяет явно указать, является ли строка пустой или нулевой.
Стандартная библиотека Go не предоставляет встроенного типа NullString, но можно создать его самостоятельно, используя структуру или указатель на строку.
Тип NullString также бывает полезен для десериализации JSON-данных в нестандартном формате. С его помощью можно создавать собственные функции наподобие Unmarshal.
В качестве примера создадим кастомный десериализатор с использованием NullString.
Декодирование неизвестных данных
Зачастую в JSON хранятся данные разных типов, которые необходимо правильно обработать. В этом случае может помочь декодирование значений в интерфейс и их последующий перебор с использованием switch-case. Такой подход позволяет сохранить преимущества безопасности типов.
Для детального понимания рассмотрим конкретный пример.
Вывод будет следующий: