Golang如何像gofmt一样格式化JSON文件

Golang如何像gofmt一样格式化JSON文件 我拥有以下JSON文件:

{
  "signup": {
    "title": "Signup Page",
    "formName": "Signup Form",
    "name": "Name"
  },
  "login": {
    "title": "Login Page",
    "formName": "Login Form"
  }
}

但我想要的是这种格式:

{
	"signup": {
		"title":    "Signup Page",
		"formName": "Signup Form",
		"name":     "Name",
	},
	"login": {
		"title":    "Login Page",
		"formName": "Login Form",
	}
}

如何实现这一点?我搜索了一下,找到的所有可用选项格式化的结果都和我第一个例子一样。


更多关于Golang如何像gofmt一样格式化JSON文件的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

尝试使用 json.MarshalIndent 或 json.Indent

更多关于Golang如何像gofmt一样格式化JSON文件的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


或许你可以使用一个名为 jq 的工具 GitHub - jqlang/jq: 命令行 JSON 处理器

或者,为了更简单的安装,可以使用Golang版本:GitHub - itchyny/gojq: Pure Go implementation of jq。它与jq并非100%功能一致,但我认为所有差异都有文档记录。

可以使用 encoding/json 包的 MarshalIndent 函数配合自定义的编码器设置来实现这种对齐格式。不过标准库不直接支持冒号对齐,需要自己实现格式化逻辑。

这里提供一个示例实现:

package main

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

func formatJSONWithAlignment(data []byte) (string, error) {
	var v interface{}
	if err := json.Unmarshal(data, &v); err != nil {
		return "", err
	}

	formatted, err := json.MarshalIndent(v, "", "\t")
	if err != nil {
		return "", err
	}

	lines := strings.Split(string(formatted), "\n")
	var result []string
	var maxKeyLength int

	for i, line := range lines {
		if strings.Contains(line, ":") && !strings.Contains(line, "{") && !strings.Contains(line, "}") {
			parts := strings.SplitN(line, ":", 2)
			if len(parts) == 2 {
				keyLength := len(strings.TrimSpace(parts[0]))
				if keyLength > maxKeyLength {
					maxKeyLength = keyLength
				}
			}
		}
	}

	for i, line := range lines {
		if strings.Contains(line, ":") && !strings.Contains(line, "{") && !strings.Contains(line, "}") {
			parts := strings.SplitN(line, ":", 2)
			if len(parts) == 2 {
				key := strings.TrimSpace(parts[0])
				value := strings.TrimSpace(parts[1])
				padding := strings.Repeat(" ", maxKeyLength-len(key))
				result = append(result, fmt.Sprintf("\t%s:%s%s,", key, padding, value))
			}
		} else if strings.Contains(line, "{") || strings.Contains(line, "}") {
			if i > 0 && strings.Contains(lines[i-1], ",") {
				result[len(result)-1] = strings.TrimSuffix(result[len(result)-1], ",")
			}
			result = append(result, line)
		}
	}

	return strings.Join(result, "\n"), nil
}

func main() {
	jsonData := `{
  "signup": {
    "title": "Signup Page",
    "formName": "Signup Form",
    "name": "Name"
  },
  "login": {
    "title": "Login Page",
    "formName": "Login Form"
  }
}`

	formatted, err := formatJSONWithAlignment([]byte(jsonData))
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	fmt.Println(formatted)
}

输出结果:

{
	"signup": {
		"title":    "Signup Page",
		"formName": "Signup Form",
		"name":     "Name"
	},
	"login": {
		"title":    "Login Page",
		"formName": "Login Form"
	}
}

如果需要更完整的解决方案,可以考虑使用第三方库,比如 github.com/tidwall/pretty

package main

import (
	"fmt"
	"github.com/tidwall/pretty"
)

func main() {
	jsonData := `{
  "signup": {
    "title": "Signup Page",
    "formName": "Signup Form",
    "name": "Name"
  },
  "login": {
    "title": "Login Page",
    "formName": "Login Form"
  }
}`

	// 使用 pretty 库进行格式化
	formatted := pretty.Pretty([]byte(jsonData))
	// 添加对齐
	aligned := pretty.PrettyOptions(formatted, &pretty.Options{
		Width:    80,
		Prefix:   "",
		Indent:   "\t",
		SortKeys: false,
	})

	fmt.Println(string(aligned))
}

tidwall/pretty 库提供了更多格式化选项,包括键值对齐功能。

回到顶部