我有一个枚举定义为
1 2 3 4 5 | type MyEnum int const( FirstEnum MyEnum = iota ) |
然后,我有一个具有键值对
1 2 3 | var data map[string]interface{} err := json.Unmarshal([]byte(json), &data) x := data["key"].(MyEnum) |
但是,当我运行此命令时,出现错误:
1 2 | panic: interface conversion: interface {} is string, not ps.Protocol [recovered] panic: interface conversion: interface {} is string, not ps.Protocol |
有没有一种方法可以像在Go中将枚举的字符串表示形式正常转换为枚举类型一样工作?
-
首先,这完全不能与
interface{} 一起使用,因为解组器会将其解组为默认的字符串类型。 因此,您需要一个结构。 然后,您需要编写一个自定义UnmarshalJSON 函数来为您处理事务。 - 这听起来像很多工作...如何处理将json编组为自定义类型? 总是需要编写自定义解组器吗?
-
只需阅读文档。 声明一个结构,创建一个指向结构实例的指针,然后直接在
Unmarshal 中使用它 - 您不一定总是需要编写自定义拆组器。 仅当您想要自定义行为时。
我发现了一些类似的方式(至少适用于我目前的情况):
将
1 2 3 4 5 | type MyEnum string const( FirstEnum MyEnum ="FirstEnum" ) |
现在,使用解码json自定义类型,如此处所述。
1 2 | data := MyJsonStruct{} err := json.Unmarshal([]byte(json), &data) |
1 2 3 | type MyJsonStruct struct { Key MyEnum } |
然后,可以使MyJsonStruct实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | func (s *MyJsonStruct) UnmarshalJSON(data []byte) error { // Define a secondary type so that we don't end up with a recursive call to json.Unmarshal type Aux MyJsonStruct; var a *Aux = (*Aux)(s); err := json.Unmarshal(data, &a) if err != nil { return err } // Validate the valid enum values switch s.Key { case FirstEnum, SecondEnum: return nil default: s.Key ="" return errors.New("invalid value for Key") } } |
操场
- 如果您愿意在Go中使用字符串类型,这确实是最简单的方法。
- 如果字符串与枚举值之一不匹配,则此方法似乎不会引发任何错误。