从Golang中的Postgres jsonb列中访问值

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

Accessing values from postgres jsonb column in Golang

问题

我正在从Postgres中获取一个jsonb列,其值类似于

{
  "a": 123,
  "b": "some str",
  "c": {"d": 23},
  "e": {"f":34, "g": 434}
}

如何访问键a、b、d、f、g?谢谢

编辑:获取jsonb列"vars":

type Msg struct{
	Id int
	Vars map[string]interface{}
}
queryToGetD := "select id, vars from msg_table"
if rows, errRow := db.Query(queryToGetD); errRow != nil {
	return nil, fmt.Errorf("error while getting data \nquery %s \nerror %s", queryToGetD, err)
} else {
	func (){
		defer rows.Close()
		for rows.Next(){
			var msg Msg
			var vars string
			if err := rows.Scan(&msg.Id, &vars); err != nil{
				// 处理错误
				continue
			}else{
				if err := json.Unmarshal([]byte(vars), &msg.Vars); err != nil {
					// 处理错误
					continue
				}
				// 将msg添加到所需的切片中
			}
		}
	}
}
英文:

I am getting a jsonb column from postgres which has value something like

{
"a": 123,
"b": "some str",
"c": {"d": 23},
"e": {"f":34, "g", 434}
}

How can i access keys a, b, d, f, g? Thanks

EDIT: getting the jsonb column "vars":

type Msg struct{
	Id int
	Vars map[string]interface{}
}
queryToGetD := "select id, vars from msg_table"
if rows, errRow := db.Query(queryToGetD); errRow != nil {
	return nil, fmt.Errorf("error while getting data \nquery %s \nerror %s", queryToGetD, err)
} else {
	func (){
		defer rows.Close()
		for rows.Next(){
			var msg Msg
			var vars string
			if err := rows.Scan(&msg.Id, &vars); err != nil{
				// handle error
				continue
			}else{
				if err := json.Unmarshal([]byte(vars), &msg.Vars); err != nil {
					// handle error
					continue
				}
				// Add msg to the needed slice
			}
		}
	}
}

答案1

得分: 2

对于变量a和b,你可以使用msg.Vars["a"]msg.Vars["b"]来访问它们的值。对于d、f和g,你需要首先访问它们的父级,就像访问a和b一样。然后,你需要对访问结果进行类型断言,将其断言为map[string]interface{}类型,然后通过类型断言的结果访问所需的字段。

fmt.Println(msg.Vars["a"]) // 访问a
fmt.Println(msg.Vars["b"]) // 访问b

c := msg.Vars["c"].(map[string]interface{}) // 访问c并将其类型断言为map[string]interface{}
fmt.Println(c["d"]) // 然后访问d

https://go.dev/play/p/oZERUsL2EUY


或者使用与JSON匹配的结构体,然后你可以使用选择器表达式访问字段。

type Vars struct {
	A int    `json:"a"`
	B string `json:"b"`
	C struct {
		D int `json:"d"`
	} `json:"c"`
	E struct {
		F int `json:"f"`
		G int `json:"g"`
	} `json:"e"`
}

// ...

fmt.Println(msg.Vars.A)
fmt.Println(msg.Vars.B)
fmt.Println(msg.Vars.C.D)
fmt.Println(msg.Vars.E.F)
fmt.Println(msg.Vars.E.G)

https://go.dev/play/p/6ur78SNB_bL

英文:

For a and b you can do msg.Vars["a"] and msg.Vars["b"] respectively to access those values. For d, f, and g you need to first access their parents just like you would access a and b. Then you need to type-assert the result of that access to the map[string]interface{} type and then access the desired fields through the result of the type assertion.

fmt.Println(msg.Vars["a"]) // access a
fmt.Println(msg.Vars["b"]) // access b

c := msg.Vars["c"].(map[string]interface{}) // access c and type-assert as map[string]interface{}
fmt.Println(c["d"]) // then access d

https://go.dev/play/p/oZERUsL2EUY


Or use a struct that matches the json, then you can access the fields with the selector expression

type Vars struct {
	A int    `json:"a"`
	B string `json:"b"`
	C struct {
		D int `json:"d"`
	} `json:"c"`
	E struct {
		F int `json:"f"`
		G int `json:"g"`
	} `json:"e"`
}

// ...

fmt.Println(msg.Vars.A)
fmt.Println(msg.Vars.B)
fmt.Println(msg.Vars.C.D)
fmt.Println(msg.Vars.E.F)
fmt.Println(msg.Vars.E.G)

https://go.dev/play/p/6ur78SNB_bL

huangapple
  • 本文由 发表于 2021年12月31日 15:45:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/70540102.html
匿名

发表评论

匿名网友

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

确定