Обработка данных JSON с помощью Go

Предоставление разработчикам возможности легко и эффективно создавать высокопроизводительные масштабируемые веб-сервисы — одно из главных преимуществ Golang.

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

  • Продемонстрировать, как работать с модулем JSON, встроенным в стандартную библиотеку Go.
  • Покажите, как преобразовывать данные JSON в объекты Go и наоборот.
  • Расскажите о некоторых полезных инструментах, которые могут ускорить процесс работы с JSON.

Go имеет очень мощную стандартную библиотеку. Для работы с данными JSON нам не нужно извлекать какие-либо сторонние библиотеки, так как во встроенной есть все необходимое.

Давайте посмотрим на фрагмент кода, который выполняет некоторые базовые манипуляции с JSON:

Это очень простой пример, в котором мы берем фрагмент структур Go (в данном случае книг) и сериализуем его в формате JSON, чтобы мы могли отправить его по сети клиенту, запрашивающему эти данные.

Одна из первых вещей, которую вы, возможно, заметили, — это то, как мы определяем поля структуры Book. Каждый атрибут нашей структуры определяет, как он будет отображаться при сериализации в JSON в обратных кавычках (json:”title”).

Это очень полезная функция Go, которую можно легко протестировать, изменив, например, title на book_title. Это может быть очень полезно, когда возникает необходимость изменить формат вашего ответа JSON в REST API.

Теперь давайте посмотрим, как мы на самом деле преобразовали данные — метод Marshal принимает пустой интерфейс (это означает, что вы можете передать буквально любую структуру данных Go, которая вам нравится), и пытается сериализовать данные. Если это невозможно, вы получите сообщение об ошибке. Вот почему очень важно проверять ошибки. Если сериализация прошла успешно, она вернет часть байтов, готовых к передаче по сети.

Давайте посмотрим на обратную ситуацию, поток данных JSON поступает, и его нужно преобразовать в структуру данных Go, чтобы программа Go могла манипулировать данными:

Очевидно, что здесь мы в значительной степени обращаем процесс вспять, но есть одна важная вещь, на которую следует обратить внимание: при разупорядочении данных нам нужно передать указатель на срез Book структур, а не на фактический срез. Это связано с тем, что Go, в отличие от Java или Python, является языком передачи по значению. Это означает, что если мы хотим изменить состояние переменной, нам нужно использовать ее указатель, иначе будет передана только копия этой переменной, а состояние исходной переменной останется неизменным.

Помимо методов json.Marshal/json.Unmarshal, используемых в этих примерах, существует еще один подход к сериализации JSON с использованием метода json.Decoder/json.Encoder.

Основное отличие состоит в том, что эти двое ожидают чтения из некоторой структуры Go, которая реализует io.Reader interface. Тело запроса входящего HTTP-запроса является одним из них. Не создавая весь HTTP-сервер, давайте рассмотрим ситуацию, когда мы принимаем запрос от HTTP-клиента на добавление новой книги в нашу коллекцию:

Таким образом, при реализации обработчика HTTP-запросов использование json.NewDecoder/json.NewEncoder может иметь больше смысла, чем использование json.Marshal/json.UnMarshal.

Теперь работать с этими простыми примерами — это одно, но как насчет реальных жизненных ситуаций, когда запрос/ответ JSON обычно представляет собой большую структуру, полную вложенных объектов. Реализация почти такая же, за исключением того, что определение структур Go может легко превратиться в головную боль. После того, как я вручную написал структуры несколько раз, я нашел чрезвычайно полезный инструмент для автоматического выполнения этого. Вы можете найти это здесь".

Давайте посмотрим на пример из API Рика и Морти. Вы можете увидеть ответ HTTP, вызвав:

https://rickandmortyapi.com/api/character/418

Когда вы вставляете ответ в инструмент JSON-to-Go, вы получаете:

Довольно быстрое преобразование! Нет необходимости вручную вводить структуру и выяснять, какой вложенный объект JSON нужно преобразовать в какую структуру Go.

Подождите, вы говорите, что вам на самом деле не нужна структура Go, но вместо этого вы предпочитаете карту Go? Не беспокойтесь, вы можете легко сделать преобразование здесь:

Это все для этой статьи. Я надеюсь, что вы сочли полезным. Спасибо за прочтение!