如何在Go中无需额外转义/编组将含空格制表符的原始JSON传入结构体
解决Go结构体编组时JSON字符串额外转义问题
核心方案:为BrandTemplate实现自定义MarshalJSON方法
如果你不想修改BrandTemplate的字段类型(保持Template为string),可以通过实现json.Marshaler接口,手动控制结构体的JSON编组逻辑,让Template字段直接输出原始JSON内容而非转义后的字符串。
代码实现
import ( "encoding/json" "errors" ) type BrandTemplate struct { Type string `json:"type"` // Template type (e.g., email_forgot_password) Locale string `json:"locale"` // Locale (e.g., "es" for Spanish, "en" for English) Template string `json:"template"` // Template content (Email/SMS content) } // MarshalJSON 自定义编组逻辑,避免Template字段被转义 func (bt BrandTemplate) MarshalJSON() ([]byte, error) { // 先验证Template是否是合法JSON,避免输出无效JSON if !json.Valid([]byte(bt.Template)) { return nil, errors.New("template is not valid JSON") } // 构造临时结构体,将Template转为json.RawMessage type TempBrandTemplate struct { Type string `json:"type"` Locale string `json:"locale"` Template json.RawMessage `json:"template"` } temp := TempBrandTemplate{ Type: bt.Type, Locale: bt.Locale, Template: json.RawMessage(bt.Template), } // 编组临时结构体,此时Template会以原始JSON形式输出 return json.Marshal(temp) }
使用示例
// 定义原始JSON模板字符串 template := `{ "subject": "Email MFA App Verification Code", "html": "<html><head></head><body><p>Here is the code: {{otp_code}}</p></body></html>", "plain": "Here is the code: {{otp_code}}" }` brandTemplate := BrandTemplate{ Type: "email_code_app_verification", Locale: "en", Template: template, } // 编组结构体,此时Template字段不会被额外转义 result, err := json.MarshalIndent(brandTemplate, "", " ") if err != nil { panic(err) } println(string(result))
输出效果
编组后的JSON会将template字段作为原始JSON对象输出,而非转义字符串:
{ "type": "email_code_app_verification", "locale": "en", "template": { "subject": "Email MFA App Verification Code", "html": "<html><head></head><body><p>Here is the code: {{otp_code}}</p></body></html>", "plain": "Here is the code: {{otp_code}}" } }
补充:反序列化的处理(可选)
如果需要将JSON反序列化为BrandTemplate结构体,同时让Template字段保留原始JSON字符串,还需要实现json.Unmarshaler接口:
// UnmarshalJSON 自定义反序列化逻辑 func (bt *BrandTemplate) UnmarshalJSON(data []byte) error { type TempBrandTemplate struct { Type string `json:"type"` Locale string `json:"locale"` Template json.RawMessage `json:"template"` } var temp TempBrandTemplate if err := json.Unmarshal(data, &temp); err != nil { return err } bt.Type = temp.Type bt.Locale = temp.Locale bt.Template = string(temp.Template) return nil }
注意事项
- 必须确保
Template字段的字符串是合法的JSON,否则自定义编组会返回错误。如果需要支持非JSON格式的模板内容,建议保留默认的字符串转义逻辑,或者在验证失败时fallback到默认处理。 - 自定义编组/反序列化方法会覆盖默认的JSON处理逻辑,后续如果结构体字段有修改,需要同步更新这些方法。
内容的提问来源于stack exchange,提问作者Sparsh
相关产品推荐
相关产品推荐

