Home > front end >  Parsing complex JSON, again
Parsing complex JSON, again

Time:01-14

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"

CodePudding user response:

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

  •  Tags:  
  • Related