Skip to content

打印函数

迁移参考

本页为 Print 系列函数(已在早期版本移除)的迁移指南。如需格式化 JSON,请使用 Prettify 或标准库兼容的 MarshalIndent

API 变更说明

Print、PrintPretty、PrintE、PrintPrettyE 已从库中移除,不再提供。请使用以下替代方案。

替代方案

打印紧凑 JSON

使用 fmt.Println + EncodeWithConfig(推荐)或 Marshal

go
data := map[string]any{"name": "Alice", "age": 30}

s, err := json.EncodeWithConfig(data)
if err != nil {
    log.Fatal(err)
}
fmt.Println(s)
// 输出:{"age":30,"name":"Alice"}

// 或者使用 Marshal([]byte 输出)
b, err := json.Marshal(data)
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(b))

Encode 已废弃

json.Encode 已标记为废弃(与 EncodeWithConfig 功能等价),将在未来主版本移除。新代码请使用 EncodeWithConfigMarshal

打印格式化 JSON

使用 fmt.Println + EncodePretty

go
s, err := json.EncodePretty(data)
if err != nil {
    log.Fatal(err)
}
fmt.Println(s)
// 输出:
// {
//   "age": 30,
//   "name": "Alice"
// }

打印 JSON 字符串(美化已有 JSON)

使用 Prettify

go
pretty, err := json.Prettify(`{"name":"Alice","age":30}`)
if err != nil {
    log.Fatal(err)
}
fmt.Println(pretty)
// 输出:
// {
//   "name": "Alice",
//   "age": 30
// }

使用 Processor 打印

go
p, err := json.New()
if err != nil {
    panic(err)
}
defer p.Close()

// 编码并打印(推荐 EncodeWithConfig;Encode 已废弃)
s, err := p.EncodeWithConfig(data)
if err != nil {
    log.Fatal(err)
}
fmt.Println(s)

// 格式化打印
pretty, err := p.EncodePretty(data)
if err != nil {
    log.Fatal(err)
}
fmt.Println(pretty)

格式化工具对照

按「输入是 Go 值还是 JSON 文本」选择工具:

函数输入输出典型用途
Marshal(v, cfg...)Go 值[]byte 紧凑标准库签名,最通用
EncodeWithConfig(v, cfg...)Go 值string 紧凑推荐入口(可带配置)
EncodePretty(v, cfg...)Go 值string 缩进直接编码并美化
MarshalIndent(v, prefix, indent)Go 值[]byte 缩进标准库签名,兼容旧代码
Prettify(jsonStr, cfg...)JSON 文本string 缩进美化已有 JSON 文本
Compact(dst, src)JSON 文本写入 *bytes.Buffer压缩已有文本
CompactString(jsonStr)JSON 文本string 紧凑压缩已有文本(免 buffer)
Indent(dst, src, prefix, indent)JSON 文本写入 *bytes.Buffer重排缩进
HTMLEscape(dst, src)JSON 文本写入 *bytes.Buffer转义 < > &
NewEncoder(w) + SetIndentGo 值写入 io.Writer流式输出(文件/网络)

三步选型

  1. 输入是 Go 值:要 []byteMarshal,要 stringEncodeWithConfig;需要缩进时分别换 MarshalIndentEncodePretty
  2. 输入已是 JSON 文本:美化用 Prettify,压缩用 CompactString;需要与标准库签名完全一致时用 buffer 版 Compact/Indent
  3. 输出到(文件/网络):NewEncoder + SetIndent 逐条写出,避免整块拼大字符串

自定义缩进

EncodePretty 默认两空格缩进。需要其他缩进时用 Config.Pretty + Config.Indent,或直接用标准库签名的 MarshalIndent

go
package main

import (
	"fmt"

	"github.com/cybergodev/json"
)

func main() {
	data := map[string]any{"name": "Alice", "age": 30}

	// 方式一:标准库签名 MarshalIndent(prefix 通常留空)
	b, err := json.MarshalIndent(data, "", "    ")
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))
	// 输出:
	// {
	//     "age": 30,
	//     "name": "Alice"
	// }

	// 方式二:EncodePretty + 配置(制表符缩进)
	cfg := json.DefaultConfig()
	cfg.Pretty = true
	cfg.Indent = "\t"
	s, err := json.EncodePretty(data, cfg)
	if err != nil {
		panic(err)
	}
	fmt.Println(s)
}

TIP

json.PrettyConfig() 是现成预设:默认配置 + Pretty: true + 两空格缩进,等价于 EncodePretty 的默认行为。

处理已有 JSON 文本

手里已经是 JSON 文本(如日志、接口返回)时,用格式化函数原地转换,无需再走一遍结构体:

go
package main

import (
	"bytes"
	"fmt"

	"github.com/cybergodev/json"
)

func main() {
	pretty := "{\n  \"name\": \"Alice\",\n  \"age\": 30\n}"

	// 压缩:去除所有非必要空白
	var compact bytes.Buffer
	if err := json.Compact(&compact, []byte(pretty)); err != nil {
		panic(err)
	}
	fmt.Println(compact.String())
	// 输出:{"name":"Alice","age":30}

	// 免 buffer 版:CompactString 直接返回字符串
	s, err := json.CompactString(pretty)
	if err != nil {
		panic(err)
	}
	fmt.Println(s)

	// 重排:换一种缩进风格
	var reindented bytes.Buffer
	if err := json.Indent(&reindented, []byte(pretty), "", "\t"); err != nil {
		panic(err)
	}
	fmt.Println(reindented.String())
	// 输出:
	// {
	// 	"name": "Alice",
	// 	"age": 30
	// }
}

HTML 安全转义

HTMLEscape 与标准库签名一致:把 JSON 文本中的 <>&、U+2028、U+2029 转义为 \u00XX 形式,防止 JSON 内嵌 HTML 时被浏览器误解析。它做的是字符级转义,不重新编码、不改空白:

go
package main

import (
	"bytes"
	"fmt"

	"github.com/cybergodev/json"
)

func main() {
	src := []byte(`{"html":"<b>bold</b>","url":"a&b"}`)

	var buf bytes.Buffer
	json.HTMLEscape(&buf, src)
	out := buf.String()
	fmt.Println(out)
	// 输出的引号内不再有裸露的 <、>、&,
	// 它们分别被替换为 \u00XX 形式的转义序列,其余内容原样保留
}

什么时候需要手动转义?

Marshal/EncodeWithConfig 默认已开启 HTML 转义(Config.EscapeHTML: true),编码产物本身是安全的。HTMLEscape 主要用于处理外部拿到的 JSON 文本——比如要把第三方返回的 JSON 原样内嵌到 HTML 页面时,先过一遍再输出。

流式输出到 Writer

写文件或网络流时,用 NewEncoder(标准库签名)避免整块拼字符串:

go
package main

import (
	"os"

	"github.com/cybergodev/json"
)

func main() {
	type Item struct {
		ID   int    `json:"id"`
		Name string `json:"name"`
	}

	enc := json.NewEncoder(os.Stdout)
	enc.SetIndent("", "  ")

	for _, item := range []Item{{1, "Alice"}, {2, "Bob"}} {
		if err := enc.Encode(item); err != nil {
			panic(err)
		}
	}
	// 输出:
	// {
	//   "id": 1,
	//   "name": "Alice"
	// }
	// {
	//   "id": 2,
	//   "name": "Bob"
	// }
}

Encoder.Encode 与标准库一致,每条记录后自动换行——逐条输出日志、写 JSONL 文件都很自然。

完整示例

go
package main

import (
	"fmt"
	"github.com/cybergodev/json"
	"log"
)

func main() {
	data := map[string]any{
		"users": []any{
			map[string]any{"id": 1, "name": "Alice"},
			map[string]any{"id": 2, "name": "Bob"},
		},
		"total": 2,
	}

	// 紧凑输出(Encode 已废弃,推荐 EncodeWithConfig)
	compact, err := json.EncodeWithConfig(data)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(compact)

	// 格式化输出
	pretty, err := json.EncodePretty(data)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(pretty)
}

相关