Как красиво вывести JSON в Go: полный гайд с примерами

Онлайн-тренажер Python для начинающих

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

Начать курс

Почему JSON в Go выглядит как каша и как это исправить?

Вы когда-нибудь писали на Go программу, которая выводит JSON, и получали в терминале нечто подобное?

{"name":"PythonLib","year":2025,"tags":["go","json","tutorial"],"active":true}

Согласитесь, читать это без специальных инструментов — то ещё удовольствие. Особенно когда структура данных сложная, а вложенность уходит на несколько уровней. Глаза начинают разбегаться, и найти нужное поле становится настоящим квестом.

Хорошая новость: в Go есть встроенные средства, которые превращают эту «кашу» в аккуратный, структурированный документ. И сегодня мы разберём все способы красиво отформатировать JSON — от простого использования стандартной библиотеки до создания собственного pretty-print инструмента.

Этот материал основан на реальном вопросе с Stack Overflow (более 50 000 просмотров), так что тема действительно востребована. Поехали!

Что такое pretty-print и зачем он нужен?

Pretty-print (или «красивая печать») — это форматирование данных с отступами, переносами строк и выравниванием, чтобы их было удобно читать человеку. В контексте JSON это означает:

  • Добавление пробелов или табуляции для вложенных элементов
  • Перенос каждой пары «ключ-значение» на новую строку
  • Выравнивание значений для наглядности

Зачем это нужно в Go? Представьте, что вы отлаживаете API-ответ, пишете логгер или просто выводите конфигурацию. Неотформатированный JSON занимает меньше места, но совершенно нечитаем. Pretty-print решает эту проблему за пару строк кода.

Способ 1: json.MarshalIndent — стандартное решение

Самый простой и рекомендуемый способ — использовать функцию json.MarshalIndent из стандартного пакета encoding/json. Она делает ровно то, что нужно: принимает данные и возвращает отформатированный JSON с отступами.

Вот базовый пример:

package main

import (
    "encoding/json"
    "fmt"
    "log"
)

type Site struct {
    Name   string   `json:"name"`
    Year   int      `json:"year"`
    Tags   []string `json:"tags"`
    Active bool     `json:"active"`
}

func main() {
    site := Site{
        Name:   "PythonLib",
        Year:   2025,
        Tags:   []string{"go", "json", "tutorial"},
        Active: true,
    }

    // Префикс — "", отступ — "  " (два пробела)
    prettyJSON, err := json.MarshalIndent(site, "", "  ")
    if err != nil {
        log.Fatalf("Ошибка маршалинга: %v", err)
    }

    fmt.Println(string(prettyJSON))
}

Результат:

{
  "name": "PythonLib",
  "year": 2025,
  "tags": [
    "go",
    "json",
    "tutorial"
  ],
  "active": true
}

Красиво, правда? Обратите внимание на второй и третий параметры MarshalIndent:

  • Префикс — строка, которая добавляется в начало каждой строки. Обычно пустая строка "".
  • Отступ — строка для каждого уровня вложенности. Чаще всего используют два пробела " " или табуляцию "\t".

Настройка отступов: пробелы vs табуляция

Вы можете легко менять стиль отступов. Например, с табуляцией:

prettyJSON, _ := json.MarshalIndent(site, "", "\t")
fmt.Println(string(prettyJSON))

Результат:

{
	"name": "PythonLib",
	"year": 2025,
	"tags": [
		"go",
		"json",
		"tutorial"
	],
	"active": true
}

Какой вариант выбрать? Если ваш проект следует стандартам Go (а они рекомендуют табуляцию для кода), используйте "\t". Если вы работаете в команде, где приняты пробелы — два пробела будут уместнее. Главное — единообразие.

Способ 2: Pretty-print для сырых строк JSON

А что, если у вас уже есть строка с неотформатированным JSON? Например, вы получили её из HTTP-запроса или прочитали из файла. В этом случае сначала нужно распарсить строку в interface{}, а потом снова сериализовать с отступами.

package main

import (
    "encoding/json"
    "fmt"
    "log"
)

func main() {
    // Неотформатированный JSON
    rawJSON := `{"name":"PythonLib","year":2025,"tags":["go","json","tutorial"],"active":true}`

    // Шаг 1: распарсить в interface{}
    var data interface{}
    err := json.Unmarshal([]byte(rawJSON), &data)
    if err != nil {
        log.Fatalf("Ошибка парсинга: %v", err)
    }

    // Шаг 2: отформатировать
    prettyJSON, err := json.MarshalIndent(data, "", "  ")
    if err != nil {
        log.Fatalf("Ошибка форматирования: %v", err)
    }

    fmt.Println(string(prettyJSON))
}

Этот подход универсален: он работает с любым валидным JSON, независимо от структуры. Единственный минус — вы теряете информацию о типах (всё хранится как map[string]interface{}), но для pretty-print это неважно.

Способ 3: Кастомный pretty-print с помощью bytes.Buffer

Иногда нужно не просто вывести JSON в консоль, а записать его в файл, отправить по сети или использовать в логгере. Для таких случаев удобно использовать bytes.Buffer в паре с json.Indent.

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "log"
)

func main() {
    data := map[string]interface{}{
        "name": "PythonLib",
        "year": 2025,
        "tags": []string{"go", "json", "tutorial"},
        "nested": map[string]interface{}{
            "active": true,
            "score":  9.5,
        },
    }

    // Сериализуем без форматирования
    rawJSON, err := json.Marshal(data)
    if err != nil {
        log.Fatalf("Ошибка маршалинга: %v", err)
    }

    // Форматируем через буфер
    var prettyBuf bytes.Buffer
    err = json.Indent(&prettyBuf, rawJSON, "", "  ")
    if err != nil {
        log.Fatalf("Ошибка индентации: %v", err)
    }

    fmt.Println(prettyBuf.String())
}

Преимущество этого метода — вы получаете bytes.Buffer, который можно использовать дальше: записать в файл, передать в логгер или даже отправить как HTTP-ответ.

Способ 4: Pretty-print для HTTP-ответов

Часто на практике нужно красиво вывести JSON-ответ от API. Вот пример с реальным запросом:

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "log"
    "                

Блоги

Рекомендаций по книгам