json: cannot unmarshal string into Go struct field ***.***.***.Code of type int

2025年12月16日 18:57 状态: processing

🚨 错误信息

json: cannot unmarshal string into Go struct field ***.***.***.Code of type int

🤖 AI解决方案

报错分析报告

错误翻译



原文:json: cannot unmarshal string into Go struct field ..*.Code of type int
译文:JSON:无法将字符串反序列化到Go结构体字段 ..*.Code 的 int 类型中

原因分析

这是Go语言中JSON反序列化时的类型不匹配错误:

  • 根本原因:JSON数据中的某个字段值是字符串类型,但Go结构体定义中对应的字段是int类型

  • 具体位置:结构体字段路径为 ..*.Code(实际字段路径已被星号隐藏)

  • 错误场景:使用 json.Unmarshal() 或类似方法解析JSON时,JSON中的字符串值无法自动转换为Go的int类型
  • 解决方案

    方案一:修改JSON数据(如果可控制数据源)


    json
    {
    "Code": 200 // 改为数字而非字符串
    }

    方案二:修改Go结构体定义


    ``go
    // 错误的结构体定义
    type YourStruct struct {
    Code int
    json:"Code" // ❌ 定义为int但收到字符串
    }

    // 修复后的结构体定义
    type YourStruct struct {
    Code int
    json:"Code" // ✅ 方法1:保持int,确保JSON中为数字
    }

    // 或者使用json.Number(如果数据可能是字符串形式的数字)
    type YourStruct struct {
    Code json.Number
    json:"Code" // ✅ 方法2:使用json.Number
    }

    // 或者先定义为字符串再转换
    type YourStruct struct {
    Code string
    json:"Code" // ✅ 方法3:定义为字符串,后续转换
    }

    // 然后手动转换
    codeInt, err := strconv.Atoi(yourStruct.Code)

    方案三:自定义JSON反序列化


    go
    type YourStruct struct {
    Code int
    json:"Code"
    }

    func (s *YourStruct) UnmarshalJSON(data []byte) error {
    // 临时结构体用于处理字符串或数字
    type Alias YourStruct
    aux := &struct {
    Code interface{}
    json:"Code"
    *Alias
    }{
    Alias: (*Alias)(s),
    }

    if err := json.Unmarshal(data, &aux); err != nil {
    return err
    }

    // 处理不同类型的Code值
    switch v := aux.Code.(type) {
    case float64:
    s.Code = int(v)
    case string:
    if code, err := strconv.Atoi(v); err == nil {
    s.Code = code
    } else {
    return fmt.Errorf("Code必须是可转换为int的数字或字符串")
    }
    default:
    return fmt.Errorf("Code必须是数字或字符串")
    }

    return nil
    }

    ️ 预防措施

    1. 使用严格JSON Schema验证


  • 在API文档中明确字段类型

  • 使用JSON Schema或OpenAPI规范定义接口

  • 在开发阶段使用静态类型检查工具
  • 2. 实现防御性编程


    go
    // 创建测试验证函数
    func ValidateJSON(jsonStr string, target interface{}) error {
    // 先进行语法检查
    if !json.Valid([]byte(jsonStr)) {
    return fmt.Errorf("无效的JSON格式")
    }

    // 使用json.RawMessage延迟反序列化
    var raw map[string]json.RawMessage
    if err := json.Unmarshal([]byte(jsonStr), &raw); err != nil {
    return err
    }

    // 检查关键字段类型
    if codeData, ok := raw["Code"]; ok {
    // 尝试解析为字符串和数字
    var codeStr string
    var codeNum int

    // 先尝试字符串
    if err := json.Unmarshal(codeData, &codeStr); err == nil {
    // 验证字符串是否为有效数字
    if _, err := strconv.Atoi(codeStr); err != nil {
    return fmt.Errorf("Code字段的值'%s'无法转换为整数", codeStr)
    }
    } else if err := json.Unmarshal(codeData, &codeNum); err != nil {
    return fmt.Errorf("Code字段必须是数字或可转换为数字的字符串")
    }
    }

    // 如果所有检查通过,执行实际反序列化
    return json.Unmarshal([]byte(jsonStr), target)
    }
    ``

    ---

    建议:根据您的实际情况选择最适合的解决方案。如果是API接口开发,建议方案二结合方案三,既能处理多种数据格式,又能保持类型安全。