有没有更简单的方法在 Go 中解码这个 json?
Posted
技术标签:
【中文标题】有没有更简单的方法在 Go 中解码这个 json?【英文标题】:Is there a simpler way to decode this json in Go? 【发布时间】:2019-12-13 10:11:10 【问题描述】:我正在尝试将 Jira 中的一些 JSON 解析为变量。这是使用 go-jira 包 (https://godoc.org/github.com/andygrunwald/go-jira)
目前我有一些代码可以让开发人员:
dev := jiraIssue.Fields.Unknowns["customfield_11343"].(map[string]interface)["name"]
和team := jiraIssue.Fields.Unknowns["customfield_12046"].([]interface)[0].(map[string]interface)["value"]
获得他们所属的团队。
获取他们所在的团队有点恶心,除了必须键入 assert,设置索引,然后再次键入 assert 之外,还有更简洁的方法来获取团队吗?
这是完整的json(修改过但结构相同,太长了):
"expand":"renderedFields,names,schema,operations,editmeta,changelog,versionedRepresentations",
"id":"136944",
"self":"https://jira.redacted.com/rest/api/2/issue/136944",
"key":"RM-2506",
"fields":
"customfield_11343":
"self":"https://redacted.com/rest/api/2/user?username=flast",
"name":"flast",
"key":"flast",
"emailAddress":"flast@redacted.com",
"displayName":"first last",
"active":true,
"timeZone":"Europe/London"
,
"customfield_12046":[
"self":"https://jira.redacted.com/rest/api/2/customFieldOption/12045",
"value":"diy",
"id":"12045"
],
谢谢
【问题讨论】:
通常的做法是定义与 JSON 结构匹配的 Go 类型并解码为该类型。显示完整的 JSON。 添加了更多的 json 自定义字段有不同的值类型。类型是由字段名称决定的(“customfield_11343”就是一个例子)还是别的什么? 这个由 Jira 自己决定 值类型是任意的,还是字段名称和值类型之间是否有记录的映射? 【参考方案1】:这是一个艰难的,因为第二个是数组形式。这使得使用地图变得困难。
对于第一个,使用起来很简单:
type JiraCustomField struct
Self string `json:"self"`
Name string `json:"name"`
Key string `json:"key"`
EmailAddress string `json:"emailAddress"`
DisplayName string `json:"displayName"`
Active bool `json:"active"`
TimeZone string `json:"timeZone"`
type JiraPayload struct
Expand string `json:"expand"`
ID string `json:"id"`
Key string `json:"key"`
Fields map[string]JiraCustomField `json:"fields"`
https://play.golang.org/p/y8-g6r0kInV
特别是这部分Fields map[string]JiraCustomField
对于第二种情况,看起来您需要像Fields map[string][]JiraCustomField
这样的数组形式。
在这种情况下,我认为您需要制作自己的 Unmarshaler。这是一个很好的教程:https://blog.gopheracademy.com/advent-2016/advanced-encoding-decoding/
您可以使用自定义 Unmarshal/marshaler 执行的操作是使用 Reflection 包并检查它是数组还是结构。如果它是一个结构,则将其放入一个数组中,并将其存储在Fields map[string][]JiraCustomField
中。
【讨论】:
【参考方案2】:我解决此类问题的方法是:
-
复制一些我感兴趣的JSON并粘贴到https://mholt.github.io/json-to-go/
删除不感兴趣的字段。
只需读取数据并解组。
考虑到两个感兴趣的自定义字段,您最终可能会得到类似的结果,但如果您只需要名称,则可以进一步缩减结构。
type AutoGenerated struct
Fields struct
Customfield11343 struct
Self string `json:"self"`
Name string `json:"name"`
Key string `json:"key"`
EmailAddress string `json:"emailAddress"`
DisplayName string `json:"displayName"`
Active bool `json:"active"`
TimeZone string `json:"timeZone"`
`json:"customfield_11343"`
Customfield12046 []struct
Self string `json:"self"`
Value string `json:"value"`
ID string `json:"id"`
`json:"customfield_12046"`
`json:"fields"`
你得到的效果是,提要中的所有额外信息都被丢弃了,但你得到的数据却非常干净。
【讨论】:
hmm.. 所以 go-jira 所做的是返回一个 IssueFields 类型,这些自定义字段在“未知”数据中。我想我需要做类似的事情,但是将未知数的 MarshalMap 中的数据获取到我创建的结构中? 哇,好吧,所以一直以来都有一个 Unknowns 类型的 .Values() 方法。您可以访问像这样的字段dev, exists := jiraIssue.Fields.Unknowns.Value("customfield_11343/name")
。我很欣赏从答案中学到的东西
酷 :-) 如果您希望库大部分消失但仍将其用于身份验证,我认为您也可以执行 NewRawRequest t。以上是关于有没有更简单的方法在 Go 中解码这个 json?的主要内容,如果未能解决你的问题,请参考以下文章