douyin7829
2013-07-03 15:58
浏览 644

如何在Go中从json字符串获取键值

I would like to try get the key values from JSON in Go, however I'm unsure how to.

I've been able to use simplejson to read json values, however I've not been able to find out how to get the key values.

Would anyone be able to point me in the right direction and/or help me?

Thank you!

图片转代码服务由CSDN问答提供 功能建议

我想尝试从Go中的JSON获取键值,但是我不确定该怎么做。

我已经能够使用simplejson来读取json值,但是我却无法找出如何获取键值。

有人能指出正确的方向和/或帮助我吗?

谢谢!

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • doujieju0397 2013-07-03 16:17
    已采纳

    You can get the top-level keys of a JSON structure by doing:

    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    // your JSON structure as a byte slice
    var j = []byte(`{"foo":1,"bar":2,"baz":[3,4]}`)
    
    func main() {
    
        // a map container to decode the JSON structure into
        c := make(map[string]interface{})
    
        // unmarschal JSON
        e := json.Unmarshal(j, &c)
    
        // panic on error
        if e != nil {
            panic(e)
        }
    
        // a string slice to hold the keys
        k := make([]string, len(c))
    
        // iteration counter
        i := 0
    
        // copy c's keys into k
        for s, _ := range c {
            k[i] = s
            i++
        }
    
        // output result to STDOUT
        fmt.Printf("%#v
    ", k)
    
    }
    

    Note that the order of the keys must not correspond to the their order in the JSON structure. Their order in the final slice will even vary between different runs of the exact same code. This is because of how map iteration works.

    点赞 打赏 评论
  • dsx58940 2016-05-19 20:02

    If you don't feel like writing tens of useless structs, you could use either

    1. https://github.com/jmoiron/jsonq

      q := jsonq.NewQuery(`{"object": {"collection": [{"items": ["hello"]}]}}`)
      q.String("object", "collection", "items", "0") // -> "hello"
      
    2. https://github.com/tidwall/gjson

      gjson.Get(
        `{"object": {"collection": [{"items": ["hello"]}]}}`,
        "object.collection.items.0",
      ) // -> "hello"
      

      Plus some weird-useful querying tricks.

    点赞 打赏 评论
  • dth8312 2018-04-12 07:59

    I used the following to grab nested keys from JSON:

    import (
        "bytes"
        "encoding/json"
        "errors"
        "io"
        "sort"
    )
    
    func keys(b []byte) ([]string, error) {
        dec := json.NewDecoder(bytes.NewBuffer(b))
        // store unique keys
        kmap := make(map[string]struct{})
        // is the next Token a key?
        var key bool
        // keep track of both object and array parents with a slice of bools:
        //   - an object parent is true, an array parent is false
        parents := make([]bool, 0, 10)
        for {
            t, err := dec.Token()
            if err == io.EOF {
                break
            }
            if err != nil {
                return nil, err
            }
            del, ok := t.(json.Delim)
            if ok {
                if del == '{' {
                    // push an object parent
                    parents = append(parents, true)
                }
                if del == '[' {
                    // push an array parent
                    parents = append(parents, false)
                }
                if del == '}' || del == ']' {
                    if len(parents) == 0 {
                        return nil, errors.New("bad json: unexpected } or ] delim")
                    }
                    // pop the last parent
                    parents = parents[:len(parents)-1]
                }
                if len(parents) > 0 && parents[len(parents)-1] {
                    // if we are within an object, the next token must be a key
                    key = true
                } else {
                    // otherwise we are in an array, and the next token is an array entry
                    key = false
                }
                continue
            }
            if key {
                str, ok := t.(string)
                if !ok {
                    return nil, errors.New("bad json: keys must be strings")
                }
                kmap[str] = struct{}{}
                // if this is a key, then the next token is the value
                key = false
            } else if len(parents) > 0 && parents[len(parents)-1] {
                // if this is a value, and we are within an object, then the next token is a new key
                key = true
            }
        }
        // now turn our map of keys into a sorted slice
        ret := make([]string, len(kmap))
        var i int
        for k := range kmap {
            ret[i] = k
            i++
        }
        sort.Strings(ret)
        return ret, nil
    }
    
    点赞 打赏 评论

相关推荐 更多相似问题