英文:
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.metadataandworkflow.items[i].spec.argumentsis 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 
[]structseems 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论