Golang中JSON反序列化string/int64转int64失败如何解决?
解决JSON字段同时存在字符串与数值类型的反序列化问题
首先修正你原代码中的JSON语法错误:原字符串里的"id":"1000,和"id":"1001,未闭合引号,正确的JSON应为:
[{"id":"1000","price":"30"},{"id":"1001","price":50}]
针对字段类型不统一的问题,推荐以下两种解决方案:
方案一:自定义结构体的UnmarshalJSON方法(推荐)
给Item类型实现自定义反序列化逻辑,兼容字符串和数值类型的字段:
import ( "encoding/json" "fmt" "strconv" ) type Item struct { Id int64 `json:"id"` Price int64 `json:"price"` } // 自定义UnmarshalJSON方法,处理多类型字段 func (i *Item) UnmarshalJSON(data []byte) error { // 定义临时结构体,用interface{}接收字段,兼容字符串和数值 type tempItem struct { Id interface{} `json:"id"` Price interface{} `json:"price"` } var temp tempItem if err := json.Unmarshal(data, &temp); err != nil { return err } // 处理Id字段 switch val := temp.Id.(type) { case string: num, err := strconv.ParseInt(val, 10, 64) if err != nil { return fmt.Errorf("id字段转换失败:%w", err) } i.Id = num case float64: // JSON数值默认解析为float64 i.Id = int64(val) default: return fmt.Errorf("不支持的id类型:%T", val) } // 处理Price字段 switch val := temp.Price.(type) { case string: num, err := strconv.ParseInt(val, 10, 64) if err != nil { return fmt.Errorf("price字段转换失败:%w", err) } i.Price = num case float64: i.Price = int64(val) default: return fmt.Errorf("不支持的price类型:%T", val) } return nil } func HandleJsonData() { jsonData := []byte(`[{"id":"1000","price":"30"},{"id":"1001","price":50}]`) var items []Item err := json.Unmarshal(jsonData, &items) if err != nil { fmt.Println(err) return } fmt.Printf("反序列化结果:%+v\n", items) }
原理说明
通过临时结构体的interface{}字段接收任意类型的JSON值,再通过类型断言判断字段实际类型,将字符串或float64转换为int64后赋值给目标结构体字段,完成兼容反序列化。
方案二:使用json.Number类型中转
利用json.Number类型可以同时接收字符串和数值类型的特性,先完成反序列化,再手动转换为int64:
import ( "encoding/json" "fmt" ) type TempItem struct { Id json.Number `json:"id"` Price json.Number `json:"price"` } type Item struct { Id int64 `json:"id"` Price int64 `json:"price"` } func HandleJsonData() { jsonData := []byte(`[{"id":"1000","price":"30"},{"id":"1001","price":50}]`) var tempItems []TempItem err := json.Unmarshal(jsonData, &tempItems) if err != nil { fmt.Println(err) return } // 转换为业务结构体 var items []Item for _, temp := range tempItems { id, err := temp.Id.Int64() if err != nil { fmt.Printf("转换id失败:%v\n", err) continue } price, err := temp.Price.Int64() if err != nil { fmt.Printf("转换price失败:%v\n", err) continue } items = append(items, Item{Id: id, Price: price}) } fmt.Printf("反序列化结果:%+v\n", items) }
原理说明
json.Number是标准库提供的类型,能自动解析JSON中的字符串或数值类型,之后调用其Int64()方法即可转换为目标类型,适合需要灵活处理字段的场景。
内容的提问来源于stack exchange,提问作者JJT
相关产品推荐
相关产品推荐

