Go语言中JSON数组反序列化至结构体失败问题排查
问题根源与解决方案
你遇到的错误json: cannot unmarshal array into Go value of type A,核心原因是你的JSON结构和Go结构体定义不匹配:
- 你的JSON是一个二维字符串数组(
[][]string),每个元素都是独立的字符串数组; - 但你定义的
MA是[]A,其中A是包含Arr []string字段的结构体——Go标准json包默认只会把JSON对象({"key": value}格式)映射到结构体,而你的JSON每个元素是数组而非对象,自然无法匹配A类型,导致反序列化失败。
解决方案:自定义反序列化逻辑
既然你希望用结构体处理数据且不想修改JSON格式,我们可以通过给结构体实现json.Unmarshaler接口来适配这种差异。下面提供两种可行的实现方式:
方式1:给A类型实现自定义反序列化
让A直接把JSON数组解析到自身的Arr字段:
package main import ( "encoding/json" "io/ioutil" "os" ) type A struct { Arr []string } type MA []A // 给A实现UnmarshalJSON接口,适配JSON数组格式 func (a *A) UnmarshalJSON(data []byte) error { // 直接将JSON数组解析到a.Arr字段 return json.Unmarshal(data, &a.Arr) } func UnmarshalJSON(aJsonFile string) (ma MA, err error) { jsonFile, err := os.Open(aJsonFile) if err != nil { return ma, err } defer jsonFile.Close() byteValue, err := ioutil.ReadAll(jsonFile) if err != nil { return ma, err } err = json.Unmarshal(byteValue, &ma) return ma, err }
方式2:给MA类型实现自定义反序列化
先把JSON解析成[][]string,再批量转换成[]A:
package main import ( "encoding/json" "io/ioutil" "os" ) type A struct { Arr []string } type MA []A // 给MA实现UnmarshalJSON接口,完成类型转换 func (ma *MA) UnmarshalJSON(data []byte) error { // 先解析为临时的二维字符串数组 var tempArr [][]string if err := json.Unmarshal(data, &tempArr); err != nil { return err } // 将临时数组转换为MA类型 *ma = make(MA, len(tempArr)) for idx, strArr := range tempArr { (*ma)[idx] = A{Arr: strArr} } return nil } func UnmarshalJSON(aJsonFile string) (ma MA, err error) { jsonFile, err := os.Open(aJsonFile) if err != nil { return ma, err } defer jsonFile.Close() byteValue, err := ioutil.ReadAll(jsonFile) if err != nil { return ma, err } err = json.Unmarshal(byteValue, &ma) return ma, err }
验证效果
现在调用UnmarshalJSON函数,就能成功将你的JSON数据解析成MA类型了——每个A实例的Arr字段都会对应JSON里的一组字符串数组。
内容的提问来源于stack exchange,提问作者Spedwards
相关产品推荐
相关产品推荐

