Accessing a nested value in a Go map

huangapple go评论83阅读模式
英文:

Accessing a nested value in a Go map

问题

我有一个随机的 JSON(我事先不知道模式),我将其编组为 map[string]interface{}
我还有一个表示要返回的字段值的字符串,类似于 "SomeRootKey.NestValue.AnotherNestValue"

我想要能够返回该值。有没有一种简单的方法可以访问该值,而不需要使用递归技巧?

英文:

I have a random JSON (I will not know the schema ahead of time) that I am marshaling into an map[string]interface{}.
I also have a string representing the field value I would like to return, something like "SomeRootKey.NestValue.AnotherNestValue"

I want to be able to return that value. Is there an simple way to access that value without doing some recursive tricks?

答案1

得分: 1

不使用递归?是的,可以使用循环,但没有神奇的方法可以做到。

func getKey(m interface{}, key string) (string, bool) {
L:
    for _, k := range strings.Split(key, ".") {
        var v interface{}
        switch m := m.(type) {
        case map[string]interface{}:
            v = m[k]
        case []interface{}:
            idx, err := strconv.Atoi(k)
            if err != nil || idx > len(m) {
                break L
            }
            v = m[idx]
        default:
            break L
        }
        switch v := v.(type) {
        case map[string]interface{}:
            m = v
        case []interface{}:
            m = v
        case string:
            return v, true
        default:
            break L
        }
    }
    return "", false
}

使用类似以下的 JSON 数据:

{
    "SomeRootKey": {
        "NestValue": {"AnotherNestValue": "object value"},
        "Array": [{"AnotherNestValue": "array value"}]
    }
}

你可以这样使用:

fmt.Println(getKey(m, "SomeRootKey.NestValue.AnotherNestValue"))
fmt.Println(getKey(m, "SomeRootKey.Array.0.AnotherNestValue"))

[kbd] playground [/kbd]

英文:

Without recursion? yes, using a loop, but no there's no magical way to do that.

func getKey(m interface{}, key string) (string, bool) {
L:
	for _, k := range strings.Split(key, ".") {
		var v interface{}
		switch m := m.(type) {
		case map[string]interface{}:
			v = m[k]
		case []interface{}:
			idx, err := strconv.Atoi(k)
			if err != nil || idx > len(m) {
				break L
			}
			v = m[idx]
		default:
			break L
		}
		switch v := v.(type) {
		case map[string]interface{}:
			m = v
		case []interface{}:
			m = v
		case string:
			return v, true
		default:
			break L
		}
	}
	return "", false
}

Using json like:

{
	"SomeRootKey": {
		"NestValue": {"AnotherNestValue": "object value"},
		"Array": [{"AnotherNestValue": "array value"}]
	}
}

You can use:

fmt.Println(getKey(m, "SomeRootKey.NestValue.AnotherNestValue"))
fmt.Println(getKey(m, "SomeRootKey.Array.0.AnotherNestValue"))

<kbd>playground</kbd>

huangapple
  • 本文由 发表于 2014年10月6日 11:27:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/26209654.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定