解析复杂的JSON,再次解析

huangapple go评论75阅读模式
英文:

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

首先,

  1. 我猜你遇到的问题是没有使用标签。要解析 JSON,结构体的名称必须与 JSON 字段中的名称匹配。在这里阅读Golang Marshal

  2. 其次,wfMetadata 的首字母是小写,这意味着它不会被导入。

  3. 第三,workflow.metadataworkflow.items[i].spec.arguments 被设置为 {} 而不是空字符串 ""。我猜它们不应该是 string 类型。如果你不知道或不关心类型,可以使用开放的 interface{},或者根据你连接的 API 的官方文档来实现它们。

  4. 注意,我认为使用 []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

  1. 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
  2. Secondly wfMetadata has a lowecase first letter, meaning it will not be imported.
  3. Thirdly, workflow.metadata and workflow.items[i].spec.arguments is set as a {} and not the emptystring "". I assume they're not supposed to be string. This can be avoided using the open interface{} if you don't know or care, or actually implementing them using the official documentations from the API you're connecting to.
  4. 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

huangapple
  • 本文由 发表于 2022年1月13日 23:12:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/70698868.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定