Golang中JSON字符串布尔值转结构体bool字段始终为false的解决方法
问题根源
Go标准库的encoding/json仅支持将JSON原生布尔值(true/false)解析到Go的bool字段。当JSON中remember是字符串类型的"true"/"false"时,解析会失败且返回错误(你代码中未检查该错误,因此仅看到字段被设为bool的零值false)。
解决方案
方案1:自定义支持多类型的布尔类型(推荐)
通过自定义布尔类型并实现json.Unmarshaler接口,让它兼容布尔值、字符串("true"/"false")甚至数字类型的布尔表示:
package main import ( "encoding/json" "fmt" "strings" ) // 自定义Bool类型,支持解析多种格式的布尔值 type Bool bool // 实现json.Unmarshaler接口,处理不同类型的输入 func (b *Bool) UnmarshalJSON(data []byte) error { var raw interface{} if err := json.Unmarshal(data, &raw); err != nil { return err } switch val := raw.(type) { case bool: *b = Bool(val) case string: lowerStr := strings.ToLower(val) switch lowerStr { case "true", "1": *b = Bool(true) case "false", "0": *b = Bool(false) default: return fmt.Errorf("无效的布尔字符串: %s", val) } case float64: // 兼容数字1/0表示的布尔值 *b = Bool(val == 1) default: return fmt.Errorf("无法将类型%T转换为Bool", val) } return nil } type AdminInfoRequest struct { Id uint `json:"id"` UserName string `json:"username"` Password string `json:"password"` CaptchaId string `json:"captcha_id"` Captcha string `json:"captcha"` Remember Bool `json:"remember"` // 替换为自定义类型 Status uint `json:"status"` GroupId uint `json:"group_id"` OldPassword string `json:"old_password"` RePassword string `json:"re_password"` } func main() { var s AdminInfoRequest j := `{"username":"admin","remember":"true"}` // 务必检查解析错误 err := json.Unmarshal([]byte(j), &s) if err != nil { fmt.Println("解析失败:", err) return } fmt.Println(s.UserName) fmt.Println(bool(s.Remember)) // 转为原生bool使用,或直接用s.Remember }
方案2:先解析到通用Map再手动转换
如果不想自定义类型,可以先将JSON解析到map[string]interface{},再手动处理remember字段:
package main import ( "encoding/json" "fmt" "strings" ) type AdminInfoRequest struct { Id uint `json:"id"` UserName string `json:"username"` Password string `json:"password"` CaptchaId string `json:"captcha_id"` Captcha string `json:"captcha"` Remember bool `json:"remember"` Status uint `json:"status"` GroupId uint `json:"group_id"` OldPassword string `json:"old_password"` RePassword string `json:"re_password"` } func main() { var rawMap map[string]interface{} j := `{"username":"admin","remember":"true"}` err := json.Unmarshal([]byte(j), &rawMap) if err != nil { fmt.Println("解析失败:", err) return } var s AdminInfoRequest // 先解析其他类型匹配的字段,忽略remember的类型错误 _ = json.Unmarshal([]byte(j), &s) // 手动处理remember字段 if rememberVal, ok := rawMap["remember"]; ok { switch val := rememberVal.(type) { case bool: s.Remember = val case string: lowerVal := strings.ToLower(val) s.Remember = lowerVal == "true" || lowerVal == "1" case float64: s.Remember = val == 1 } } fmt.Println(s.UserName) fmt.Println(s.Remember) }
注意事项
- 永远要检查
json.Unmarshal的返回错误,它能帮你快速定位解析问题。 - 自定义类型方案更优雅,适合多个字段需要兼容多格式的场景,可统一处理逻辑。
内容的提问来源于stack exchange,提问作者xin.chen
相关产品推荐
相关产品推荐

