使用Go获取JSON数组中的特定键

时间:2022-01-17 01:33:36

I've had a heck of a time parsing JSON strings and finally landed on https://github.com/bitly/go-simplejson. It looks really promising but it's still giving me an empty result for the following JSON array:

我有一段时间解析JSON字符串,最后登陆https://github.com/bitly/go-simplejson。它看起来很有前途,但它仍然给我一个空的结果,以下JSON数组:

{
 "data": {
  "translations": [
   {
    "translatedText": "Googlebot: Deutsch, um die Luft-Speed-Geschwindigkeit einer unbeladenen Schwalbe?"
   }
  ]
 }
}

I want to get to translatedText by only specifying the key. The reason for this is my JSON structure won't be predictable and so I'd like to target any JSON array but specifying a key without knowing the full structure of the JSON array.

我想通过仅指定密钥来获得translateText。原因是我的JSON结构不可预测,所以我想定位任何JSON数组,但指定一个键而不知道JSON数组的完整结构。

This is the snippet of code I use where content contains the JSON byte array:

这是我使用的代码片段,其中内容包含JSON字节数组:

f, err := js.NewJson(content)

if err != nil {
    log.Println(err)
}

t := f.Get("translatedText").MustString()

log.Println(t)

t is always blank :( Would appreciate any pointers.

t总是空白的:(会感激任何指针。

1 个解决方案

#1


5  

The problem you have is that the function Get does not recursively search through the structure; it only does a look up for the key the at the current level.

你遇到的问题是函数Get不会递归搜索结构;它只会查找当前级别的密钥。

What you can do is to create a recursive function that searches the structure and returns the value once it is found. Below is a working example using the standard package encoding/json:

你可以做的是创建一个递归函数,搜索结构并在找到它后返回值。下面是使用标准包编码/ json的工作示例:

package main

import (
    "encoding/json"
    "fmt"
)

// SearchNested searches a nested structure consisting of map[string]interface{}
// and []interface{} looking for a map with a specific key name.
// If found SearchNested returns the value associated with that key, true
// If the key is not found SearchNested returns nil, false
func SearchNested(obj interface{}, key string) (interface{}, bool) {
    switch t := obj.(type) {
    case map[string]interface{}:
        if v, ok := t[key]; ok {
            return v, ok
        }
        for _, v := range t {
            if result, ok := SearchNested(v, key); ok {
                return result, ok
            }
        }
    case []interface{}:
        for _, v := range t {
            if result, ok := SearchNested(v, key); ok {
                return result, ok
            }
        }
    }

    // key not found
    return nil, false
}


func main() {
    jsonData := []byte(`{
 "data": {
  "translations": [
   {
    "translatedText": "Googlebot: Deutsch, um die Luft-Speed-Geschwindigkeit einer unbeladenen Schwalbe?"
   }
  ]
 }
}`)

    // First we unmarshal into a generic interface{}
    var j interface{}
    err := json.Unmarshal(jsonData, &j)
    if err != nil {
        panic(err)
    }

    if v, ok := SearchNested(j, "translatedText"); ok {
        fmt.Printf("%+v\n", v)
    } else {
        fmt.Println("Key not found")
    }

}

Result:

结果:

Googlebot: Deutsch, um die Luft-Speed-Geschwindigkeit einer unbeladenen Schwalbe?

Googlebot:Deutsch,嗯死Luft-Speed-Geschwindigkeit einer unbeladenen Schwalbe?

Playground: http://play.golang.org/p/OkLQbbId0t

游乐场:http://play.golang.org/p/OkLQbbId0t

#1


5  

The problem you have is that the function Get does not recursively search through the structure; it only does a look up for the key the at the current level.

你遇到的问题是函数Get不会递归搜索结构;它只会查找当前级别的密钥。

What you can do is to create a recursive function that searches the structure and returns the value once it is found. Below is a working example using the standard package encoding/json:

你可以做的是创建一个递归函数,搜索结构并在找到它后返回值。下面是使用标准包编码/ json的工作示例:

package main

import (
    "encoding/json"
    "fmt"
)

// SearchNested searches a nested structure consisting of map[string]interface{}
// and []interface{} looking for a map with a specific key name.
// If found SearchNested returns the value associated with that key, true
// If the key is not found SearchNested returns nil, false
func SearchNested(obj interface{}, key string) (interface{}, bool) {
    switch t := obj.(type) {
    case map[string]interface{}:
        if v, ok := t[key]; ok {
            return v, ok
        }
        for _, v := range t {
            if result, ok := SearchNested(v, key); ok {
                return result, ok
            }
        }
    case []interface{}:
        for _, v := range t {
            if result, ok := SearchNested(v, key); ok {
                return result, ok
            }
        }
    }

    // key not found
    return nil, false
}


func main() {
    jsonData := []byte(`{
 "data": {
  "translations": [
   {
    "translatedText": "Googlebot: Deutsch, um die Luft-Speed-Geschwindigkeit einer unbeladenen Schwalbe?"
   }
  ]
 }
}`)

    // First we unmarshal into a generic interface{}
    var j interface{}
    err := json.Unmarshal(jsonData, &j)
    if err != nil {
        panic(err)
    }

    if v, ok := SearchNested(j, "translatedText"); ok {
        fmt.Printf("%+v\n", v)
    } else {
        fmt.Println("Key not found")
    }

}

Result:

结果:

Googlebot: Deutsch, um die Luft-Speed-Geschwindigkeit einer unbeladenen Schwalbe?

Googlebot:Deutsch,嗯死Luft-Speed-Geschwindigkeit einer unbeladenen Schwalbe?

Playground: http://play.golang.org/p/OkLQbbId0t

游乐场:http://play.golang.org/p/OkLQbbId0t