You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 04:00:56