Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Most efficient way to access nested fields in already accessed object? #272

Closed
bmoe24x opened this issue Apr 5, 2022 · 2 comments
Closed

Comments

@bmoe24x
Copy link

bmoe24x commented Apr 5, 2022

Hi, I appreciate this library a lot, nicely done. I am newish to Go and was wondering if there is a prescribed way to achieve what I am looking to do:

Say we have the following json (from the examples) in a variable called myJson:

{
  "friends": [
    {"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
    {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
    {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
  ]
}

If I need to loop over the friends array I can do something like this (not sure this is the best way either):

gjson.Get( myJson, "friends" ).ForEach( func( _, value gjson.Result ) bool {
    ... do some stuff ...
    return true // keep iterating
})

But what if I want to now do some actions with some of the fields like friends.last and friends.age? What is the best/most common way of doing this, particularly if I have a lot of child fields? Is it something like this for any field I want to access?

gjson.Get( myJson, "friends" ).ForEach( func( _, value gjson.Result ) bool {
    ... do some stuff ...

    lastName := gjson.Get( value.Raw, "last" ).Value().(string)
    age := gjson.Get( value.Raw, "age" ).Value().(int)

    ... do some stuff with lastName and age ...

    return true // keep iterating
})

Or is there a better way to cleanly access fields assuming I know at least a subset of the fields that will almost always be present?

Appreciate any recommendations

@tidwall
Copy link
Owner

tidwall commented Apr 8, 2022

All gjson.Result have methods for converting to strings, numbers, bools and such using methods like String() and Int().
They also have the Get(path) method that allows for retrieving child values.

gjson.Get( myJson, "friends" ).ForEach( func( _, value gjson.Result ) bool {

    lastName := value.Get("last").String()
    age := value.Get("age").Int()

    return true
})

@tidwall
Copy link
Owner

tidwall commented Apr 8, 2022

The Value() method returns an interface{} that contains a Go string, float64, bool, map of values, array or values, or nil.

While this may be useful for some more advance purposes, like sharing that value with other tools, or using custom encoders on the value. It's not flexible when you just want to get data out of a Result type because it requires type assertion using the Value().(type) pattern.

Using methods like Int(), String(), Bool() will automatically convert the Result to it's logical representation such as a Result from the json string "123.10" will be converted to its numerical representation using Float() or Int().

@bmoe24x bmoe24x closed this as completed Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants