Как красиво вывести JSON в Go: удобное форматирование для отладки и логов
Используйте json.MarshalIndent для форматированного вывода JSON
Вы уже на правильном пути! В стандартной библиотеке Go есть функция json.MarshalIndent, которая делает именно то, что вам нужно. Она принимает три аргумента: данные для сериализации, префикс (обычно пустая строка) и отступ (например, пробелы или табуляция). Вот как исправить ваш код:
package main
import (
"encoding/json"
"fmt"
"log"
)
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Hobbies []string `json:"hobbies"`
Address struct {
City string `json:"city"`
Zip string `json:"zip"`
} `json:"address"`
}
func main() {
u := User{
Name: "Alice",
Age: 30,
Hobbies: []string{"reading", "coding", "hiking"},
}
u.Address.City = "Moscow"
u.Address.Zip = "101000"
// Используем json.MarshalIndent вместо json.Marshal
data, err := json.MarshalIndent(u, "", " ") // два пробела для отступа
if err != nil {
log.Fatalf("Ошибка сериализации: %v", err)
}
fmt.Println(string(data))
}
Теперь вывод будет выглядеть так:
{
"name": "Alice",
"age": 30,
"hobbies": [
"reading",
"coding",
"hiking"
],
"address": {
"city": "Moscow",
"zip": "101000"
}
}
Как это работает?
- Первый аргумент — данные, которые нужно сериализовать (ваша структура, map или срез).
- Второй аргумент — префикс. Обычно пустая строка
"", но можно задать, например,">> "для отладки. - Третий аргумент — отступ. Чаще всего используют
" "(два пробела) или"\t"(табуляция).
Дополнительные советы для удобной отладки
Если вы часто выводите JSON в консоль или логи, рекомендую создать вспомогательную функцию:
func prettyPrint(v interface{}) {
data, err := json.MarshalIndent(v, "", " ")
if err != nil {
log.Printf("Ошибка pretty-print: %v", err)
return
}
fmt.Println(string(data))
}
// Использование:
prettyPrint(u)
Также можно выводить JSON напрямую в os.Stdout или логгер:
encoder := json.NewEncoder(os.Stdout)
encoder.SetIndent("", " ")
encoder.Encode(u)
Этот способ особенно полезен, если вы работаете с потоками данных, например, в HTTP-ответах.
Почему json.Marshal не подходит?
Функция json.Marshal создаёт компактный JSON без лишних пробелов и переводов строк. Это оптимально для передачи по сети или записи в файл, но не для чтения человеком. json.MarshalIndent же добавляет форматирование, что делает вывод читаемым.
Не забывайте обрабатывать ошибки — если структура содержит несериализуемые поля (например, каналы или функции), json.MarshalIndent вернёт ошибку. Используйте log.Fatalf или возвращайте ошибку в реальном коде.
Теперь ваш JSON будет красиво отформатирован, и вы легко сможете анализировать даже сложные вложенные структуры!
<<Использование json.Encoder с настройкой отступов
Альтернативный подход — использовать json.Encoder, который позволяет гибко управлять выводом. Это особенно удобно, когда нужно записать JSON не в строку, а напрямую в файл, HTTP-ответ или логгер.
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
)
func main() {
data := map[string]interface{}{
"name": "Bob",
"age": 25,
"skills": []string{"Go", "Python", "Docker"},
}
var buf bytes.Buffer
encoder := json.NewEncoder(&buf)
encoder.SetIndent("", " ") // 4 пробела для отступа
encoder.SetEscapeHTML(false) // отключаем экранирование HTML-символов
err := encoder.Encode(data)
if err != nil {
log.Fatal(err)
}
fmt.Println(buf.String())
}
Вывод будет таким же красивым, как и в первом ответе, но с четырьмя пробелами вместо двух. Преимущества этого метода:
- Можно писать JSON напрямую в
io.Writer(файл, сокет, HTTP-ответ). - Метод
SetIndentпозволяет менять отступы на лету. SetEscapeHTML(false)полезно, если в строках есть символы<,>,&— они не будут экранироваться.
Если вам нужно просто вывести JSON в консоль для отладки, оба метода равнозначны. Выбирайте тот, который удобнее в вашем контексте.
Ответов пока нет.
Войдите чтобы оставить ответ