
本文介绍在 go 中解析原始 json 后,不依赖固定 struct 绑定,而是通过运行时动态构造目标格式(如添加/删除字段、嵌套结构、默认值填充),实现灵活的 json 格式转换,适用于数据库写入等场景。
本文介绍在 go 中解析原始 json 后,不依赖固定 struct 绑定,而是通过运行时动态构造目标格式(如添加/删除字段、嵌套结构、默认值填充),实现灵活的 json 格式转换,适用于数据库写入等场景。
在 Go 开发中,常遇到这样的需求:上游传入标准 JSON,但下游数据库或 API 要求特定字段组合(例如新增 entitlements 嵌套对象、effective_date 时间戳等),而这些字段在原始数据中并不存在。此时,直接使用 json.Unmarshal 到预定义 struct 仅完成“解析”,无法满足“重构输出”的需求——你需要的是解析 + 转换 + 序列化三步流水线。
最简洁高效的方式是:先解码为通用结构(如 map[string]interface{} 或结构体),再基于业务逻辑构造目标格式,最后用 json.Marshal 输出。避免过度设计(如自定义 UnmarshalJSON 方法),除非需高频复用或强类型约束。
以下是一个完整、可运行的示例,将原始 InterestedParties 数据转换为题中指定的目标数组格式:
package main
import (
"encoding/json"
"fmt"
)
type InterestedParties struct {
Companies []Company `json:"companies"`
CCID string `json:"eventCCID"`
}
type Company struct {
CompanyID string `json:"companyID"`
CompanyType string `json:"companyType"`
WebAPI string `json:"webAPI"`
}
type Entitlement struct {
Long string `json:"long"`
Voteable string `json:"voteable"`
Tabulation string `json:"tabulation"`
Confirm string `json:"confirm"`
}
func main() {
intPartiesJSON := `{
"companies": [
{"companyID":"COMP0001","companyType":"1","webAPI":"http://google.com"},
{"companyID":"COMP0002","companyType":"1","webAPI":"http://google.com"}
],
"eventCCID":"laksjlijivelnsvnklsnvlsv"
}`
var intParties InterestedParties
if err := json.Unmarshal([]byte(intPartiesJSON), &intParties); err != nil {
panic("failed to unmarshal: " + err.Error())
}
// ✅ 构造目标格式:每个公司映射为一个 map,注入 entitlements 和 effective_date
var result []map[string]interface{}
const effectiveDate = "2017-01-01"
for _, c := range intParties.Companies {
item := map[string]interface{}{
"companyID": c.CompanyID,
"entitlements": Entitlement{
Long: "",
Voteable: "",
Tabulation: "",
Confirm: "",
},
"effective_date": effectiveDate,
}
result = append(result, item)
}
// 序列化为目标 JSON 数组
b, err := json.Marshal(result)
if err != nil {
panic("failed to marshal: " + err.Error())
}
fmt.Println(string(b))
// 输出:
// [{"companyID":"COMP0001","entitlements":{"long":"","voteable":"","tabulation":"","confirm":""},"effective_date":"2017-01-01"},
// {"companyID":"COMP0002","entitlements":{"long":"","voteable":"","tabulation":"","confirm":""},"effective_date":"2017-01-01"}]
}✅ 关键要点说明:
- 使用
[]map[string]interface{}作为中间目标切片,天然支持动态字段增删; -
Entitlement{}字面量自动填充空字符串(零值),无需手动赋空; - 若需更严格控制字段顺序或兼容性,可改用
struct(如OutputItem)替代map[string]interface{},配合jsontag 显式声明; - 生产环境务必检查
json.Unmarshal和json.Marshal的错误返回,示例中已补充 panic 处理以强调重要性; - 如需批量处理海量数据,可考虑流式处理(
json.Decoder)或预分配result切片容量(make([]map[string]interface{}, len(intParties.Companies)))提升性能。
该方案平衡了灵活性与可读性,是 Go 中 JSON 格式适配的推荐实践。


















