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数据(如果可控制数据源)


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

方案二:修改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反序列化


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. 实现防御性编程


    // 创建测试验证函数
    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接口开发,建议方案二结合方案三*,既能处理多种数据格式,又能保持类型安全。