【问题标题】:Parsing string to enum from JSON in Golang在 Golang 中从 JSON 解析字符串到枚举
【发布时间】:2023-04-10 17:12:01
【问题描述】:

我有一个枚举定义为

type MyEnum int

const(
   FirstEnum MyEnum = iota
)

然后,我有一个包含键值对 "Key": "FirstEnum" 的 json。我是这样解组的。

var data map[string]interface{}
err := json.Unmarshal([]byte(json), &data)
x := data["key"].(MyEnum)

但是,当我运行它时,我得到了错误:

panic: interface conversion: interface {} is string, not ps.Protocol [recovered]
        panic: interface conversion: interface {} is string, not ps.Protocol

有没有办法让它像在 Go 中将枚举的字符串表示形式正常转换为枚举类型一样工作?

【问题讨论】:

  • 首先,这根本不适用于interface{},因为解组器随后会将其解组为默认类型的字符串。所以你需要一个结构。然后你需要编写一个自定义的UnmarshalJSON 函数来为你处理事情。
  • 这听起来像是很多工作...... go 如何处理将 json 解组为自定义类型?总是需要编写自定义解组器?
  • 阅读文档即可。声明一个结构,创建一个指向结构实例的指针,然后直接在Unmarshal 中使用它
  • 您并不总是需要编写自定义解组器。仅当您需要自定义行为时。

标签: json go enums unmarshalling


【解决方案1】:

我想出了一些类似的方法(至少适用于我目前的情况):

string 用于类似enum 的常量:

type MyEnum string

const(
   FirstEnum MyEnum = "FirstEnum"
)

现在,使用解码 json 来自定义类型,如提到的 here

data := MyJsonStruct{}
err := json.Unmarshal([]byte(json), &data)

MyJsonStruct 看起来像:

type MyJsonStruct struct {
    Key MyEnum
}

然后您可以让 MyJsonStruct 实现Unmarshaler 接口,这样您就可以验证给定的值。

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")
    }
}

Playground

【讨论】:

  • 如果你愿意在 Go 中使用字符串类型,这确实是最简单的方法。
  • 如果字符串与枚举值之一不匹配,这种方法似乎不会引发任何错误。
猜你喜欢
  • 2021-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-25
  • 2021-09-18
  • 2019-08-02
相关资源
最近更新 更多