Igeneous
Igeneous

Reputation: 55

How to get a JSON unique field's name and deeply nested child field's value in Golang?

I have a json file that looks like this

{
  "links": {
    "uniqueurl_1": {
      "a": {
        "b": [
          "stuff"
        ],
        "I": {
          "want": {
            "to": "morestuff",
            "go": {
              "in": {
                "here": {
                  "and": "array",
                  "itis": {
                    "very": "string",
                    "deep": "stringIwant"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

And I want to get the uniqueurl_1 (that is always different for each link), and I also want to get the "deep" field's value ("stringIwant")

I know if it's not too deeply nested, you can just create a bunch of structs in Golang, but when it's this deep would it still be the only/best way to do it?

Upvotes: 1

Views: 1359

Answers (2)

RimeBeliskner
RimeBeliskner

Reputation: 362

For this case you can use gojsonq - A simple Go package to Query over JSON Data library. Here is full list of available queries.

So if you want get the value (stringIwant), you can choose or method From or method Find.

Example below:

package main

import (
    "fmt"

    "github.com/thedevsaddam/gojsonq"
)

const json = `{
  "links": {
    "uniqueurl_1": {
      "a": {
        "b": [
          "stuff"
        ],
        "I": {
          "want": {
            "to": "morestuff",
            "go": {
              "in": {
                "here": {
                  "and": "array",
                  "itis": {
                    "very": "string",
                    "deep": "stringIwant"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}`

func main() {
    key := "uniqueurl_1"
    query := "links." + key + ".a.I.want.go.in.here.itis.deep"
    fmt.Println(gojsonq.New().JSONString(json).From(query).Get())
    fmt.Println(gojsonq.New().JSONString(json).Find(query).(string))
}

Output:

stringIwant

stringIwant

Upvotes: 2

Danilo
Danilo

Reputation: 193

in your JSON is missing opening brace. Have a try in this way:

{
  "links": {
    "uniqueurl_1": {
      "a": {
        "b": [
          "stuff"
        ],
        "I": {
          "want": {
            "to": "morestuff",
            "go": {
              "in": {
                "here": {
                  "and": "array",
                  "itis": {
                    "very": "string",
                    "deep": "stringIwant"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

And use the following code to access you data:

package main

import "encoding/json"

func UnmarshalNotSoDeep(data []byte) (NotSoDeep, error) {
    var r NotSoDeep
    err := json.Unmarshal(data, &r)
    return r, err
}

func (r *NotSoDeep) Marshal() ([]byte, error) {
    return json.Marshal(r)
}

type NotSoDeep struct {
    Links Links `json:"links"`
}

type Links struct {
    Uniqueurl1 Uniqueurl1 `json:"uniqueurl_1"`
}

type Uniqueurl1 struct {
    A A `json:"a"`
}

type A struct {
    B []string `json:"b"`
    I I        `json:"I"`
}

type I struct {
    Want Want `json:"want"`
}

type Want struct {
    To string `json:"to"`
    Go Go     `json:"go"`
}

type Go struct {
    In In `json:"in"`
}

type In struct {
    Here Here `json:"here"`
}

type Here struct {
    And  string `json:"and"` 
    Itis Itis   `json:"itis"`
}

type Itis struct {
    Very string `json:"very"`
    Deep string `json:"deep"`
}

Upvotes: 1

Related Questions