Golang自定义结构体中Unmarshal mapset报错问题咨询
解决mapset.Set无法JSON反序列化的问题
Go标准库的encoding/json包仅能处理内置类型,或实现了json.Marshaler/json.Unmarshaler接口的自定义类型。mapset.Set本身未实现反序列化接口,因此当JSON数组要解析到Set[int]类型字段时,就会抛出json: cannot unmarshal array into Go struct field A.b of type mapset.Set[int]错误。
下面提供两种可行的解决方法:
方案一:自定义包装类型并实现JSON接口
创建一个包装mapset.Set[int]的自定义类型,手动实现序列化和反序列化方法,让JSON包能正确识别处理逻辑。
package main import ( "encoding/json" "fmt" mapset "github.com/deckarep/golang-set/v2" ) // 自定义包装类型,封装mapset.Set[int] type IntSet mapset.Set[int] // 实现MarshalJSON,将Set转为JSON数组 func (s IntSet) MarshalJSON() ([]byte, error) { return json.Marshal(s.ToSlice()) } // 实现UnmarshalJSON,将JSON数组转为Set func (s *IntSet) UnmarshalJSON(data []byte) error { var nums []int if err := json.Unmarshal(data, &nums); err != nil { return err } *s = IntSet(mapset.NewSet(nums...)) return nil } // 结构体使用自定义的IntSet类型 type A struct { B IntSet `json:"b"` } func main() { // 序列化测试 a := A{B: IntSet(mapset.NewSet(1, 2, 3))} r, err := json.Marshal(a) fmt.Println(string(r), err) // 输出: {"b":[1,2,3]} <nil> // 反序列化测试 var b A err = json.Unmarshal(r, &b) fmt.Println(b.B, err) // 输出: {1 2 3} <nil> }
方案二:用切片作为中间转换层
在结构体中添加一个未导出的切片字段作为中间载体,先将JSON数组解析到切片,再手动转换为mapset.Set。
package main import ( "encoding/json" "fmt" mapset "github.com/deckarep/golang-set/v2" ) type A struct { B mapset.Set[int] `json:"b"` // 未导出的中间切片,不参与JSON序列化/反序列化 bSlice []int `json:"-"` } // 实现UnmarshalJSON,先解析到切片再转Set func (a *A) UnmarshalJSON(data []byte) error { // 定义临时结构体用于解析JSON type tempA struct { BSlice []int `json:"b"` } var t tempA if err := json.Unmarshal(data, &t); err != nil { return err } // 将切片转换为Set a.B = mapset.NewSet(t.BSlice...) return nil } // 可选:自定义序列化逻辑,将Set转为切片再序列化 func (a A) MarshalJSON() ([]byte, error) { type tempA struct { BSlice []int `json:"b"` } t := tempA{ BSlice: a.B.ToSlice(), } return json.Marshal(t) } func main() { a := A{B: mapset.NewSet(1, 2, 3)} r, err := json.Marshal(a) fmt.Println(string(r), err) // 输出: {"b":[1,2,3]} <nil> var b A err = json.Unmarshal(r, &b) fmt.Println(b.B, err) // 输出: {1 2 3} <nil> }
两种方案都能解决问题:方案一更通用,适合需要在多个场景使用Set的JSON序列化需求;方案二更轻量化,适用于单个结构体的特殊处理场景。
内容的提问来源于stack exchange,提问作者eightlay
相关产品推荐
相关产品推荐

