英文:
Parsing complex JSON, again
问题
我有一些通过 API 调用获取的 JSON 数据,现在我想使用 JSON 解析它。我按照一个在线教程来解析 JSON 使用结构体的方法,但是我的实际 JSON 比他们使用的复杂得多。这是我拥有的 JSON 的示例:
{
"metadata": {},
"items": [
{
"metadata": {
"name": "run7",
"namespace": "default",
"uid": "e218fcc4",
"creationTimestamp": "2022-01-01T00:00:00Z"
},
"spec": {
"arguments": {}
},
"status": {
"phase": "Succeeded",
"startedAt": "2022-01-01T00:00:00Z",
"finishedAt": "2022-01-01T00:00:00Z"
}
}
]
}
这是我为它创建的结构体:
type wfSpec struct {
Arguments string
}
type wfStatus struct {
Phase string
StartedAt string
FinishedAt string
}
type wfMetadata struct {
Name string
Namespace string
Uid string
CreationTimestamp string
}
type Metadata []struct {
Data string
}
type Items []struct {
wfMetadata
wfStatus
wfSpec
}
type Workflow struct {
Metadata Metadata
Items Items
}
当我尝试使用 fmt.Printf(workflows.Items.wfMetadata.Name)
打印一个值时,我得到了错误 workflows.Items.Metadata undefined (type Items has no field or method Metadata)
,所以我尝试使用 fmt.Printf(workflows)
打印整个结构体,然后我得到了这个错误 cannot use workflows (type Workflow) as type string in argument to fmt.Printf
。
我只需要从 JSON 中解析出以下数据:
"name": "run7",
"namespace": "default",
"uid": "e218fcc4",
"creationTimestamp": "2022-01-01T00:00:00Z"
请帮我解决这个问题。
英文:
I have some JSON that get via an API call and I want to now parse this using JSON, I followed an online tutorial in how to parse JSON using structs, but my actual JSON is a lot more complex than the one they used. Here is an example of the JSON I have:
{
"metadata": {},
"items": [
{
"metadata": {
"name": "run7",
"namespace": "default",
"uid": "e218fcc4",
"creationTimestamp": "2022-01-01T00:00:00Z"
},
"spec": {
"arguments": {}
},
"status": {
"phase": "Succeeded",
"startedAt": "2022-01-01T00:00:00Z",
"finishedAt": "2022-01-01T00:00:00Z"
}
}
]
}
and here is the strucs that I created for it:
type wfSpec struct{
Arguments string
}
type wfStatus struct {
Phase string
StartedAt string
FinishedAt string
}
type wfMetadata struct {
Name string
Namespace string
Uid string
CreationTimestamp string
}
type Metadata []struct {
Data string
}
type Items []struct {
wfMetadata
wfStatus
wfSpec
}
type Workflow struct {
Metadata Metadata
Items Items
}
When I first tried to print a value using fmt.Printf(workflows.Items.wfMetadata.Name)
I got the error workflows.Items.Metadata undefined (type Items has no field or method Metadata)
so then I tried to just print the whole thing using fmt.Printf(workflows)
and I got this error cannot use workflows (type Workflow) as type string in argument to fmt.Printf
The only data I need to parse from the JSON is the
"name": "run7",
"namespace": "default",
"uid": "e218fcc4",
"creationTimestamp": "2022-01-01T00:00:00Z"
答案1
得分: 1
首先,
-
我猜你遇到的问题是没有使用标签。要解析 JSON,结构体的名称必须与 JSON 字段中的名称匹配。在这里阅读Golang Marshal。
-
其次,wfMetadata 的首字母是小写,这意味着它不会被导入。
-
第三,
workflow.metadata
和workflow.items[i].spec.arguments
被设置为{}
而不是空字符串""
。我猜它们不应该是string
类型。如果你不知道或不关心类型,可以使用开放的interface{}
,或者根据你连接的 API 的官方文档来实现它们。 -
注意,我认为使用
[]struct
是错误的。相反,应该在用法中定义它们。
注意,使用像 JetBrains 的 GoLand 这样的 IDE,它们首先支持通过将 JSON 粘贴到
.go
文件中将其转换为结构体。它们可能一开始会让人望而却步,但确实非常有帮助,并且可以在几秒钟内为你完成大部分工作。
现在尝试使用下面的代码,理解为什么这样做更好并且可以正常工作。
type Status struct {
Phase string `json:"phase"`
StartedAt string `json:"startedAt"`
FinishedAt string `json:"finishedAt"`
}
type ItemMetadata struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
UID string `json:"uid"`
CreationTimestamp string `json:"creationTimestamp"`
}
type Items struct {
Metadata ItemMetadata `json:"metadata"`
Status Status `json:"status"`
Spec interface{} `json:"spec"`
}
type Workflow struct {
Metadata interface{} `json:"metadata"`
Items []Items `json:"items"`
}
在 playground 中的工作示例:https://go.dev/play/p/d9rT4FZJsGv
英文:
First off
- The problem I expect you're having is not using the tags. To parse a JSON the names of the structs must match the names in the JSON fields. Read here Golang Marshal
- Secondly wfMetadata has a lowecase first letter, meaning it will not be imported.
- Thirdly,
workflow.metadata
andworkflow.items[i].spec.arguments
is set as a{}
and not the emptystring""
. I assume they're not supposed to bestring
. This can be avoided using the openinterface{}
if you don't know or care, or actually implementing them using the official documentations from the API you're connecting to. - As a note, using
[]struct
seems wrong to me. Instead define it in the usage
> Note, by using an IDE like GoLand from jetbrains they first off support converting JSON to a struct by simply pasting the JSON into a .go
file. They might be daunting at first but do help a lot, and would do much of this for you in seconds.
Now try this instead, and understand why and how this is better and working.
type Status struct {
Phase string `json:"phase"`
StartedAt string `json:"startedAt"`
FinishedAt string `json:"finishedAt"`
}
type ItemMetadata struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
UID string `json:"uid"`
CreationTimestamp string `json:"creationTimestamp"`
}
type Items struct {
Metadata ItemMetadata `json:"metadata"`
Status Status `json:"status"`
Spec interface{} `json:"spec"`
}
type Workflow struct {
Metadata interface{} `json:"metadata"`
Items []Items `json:"items"`
}
> Working example in playground https://go.dev/play/p/d9rT4FZJsGv
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论