我有jsonb存盤在 postgres 列中的值,我需要將其轉換object為發送回應
我無法使用json.Unmarshal方法轉換 JSON -> 結構
type Result struct {
Id int
Expertise string // because json string
Languages string // because json string
}
// saving dd query data to result struct
e, _ := json.Marshal(data.Expertise)
l, _ := json.Marshal(data.Languages)
row := r.db.QueryRow(`
INSERT INTO filters (user_id, expertise, languages)
VALUES ($1, $2, $3)
ON CONFLICT (user_id) DO
UPDATE SET expertise=$2, languages=$3
RETURNING id, expertise, languages;
`, userid, e, l)
var res Result
err := row.Scan(&res.Id, &res.Expertise, &res.Languages)
然后我把這個專業和語言領域和 UNMARSHAL THEM
// helper method
func Unmarshal(value string) interface{} {
var obj interface{}
err := json.Unmarshal([]byte(value), &obj)
return obj
}
type CreateFilterResponse struct {
Id int `json:"id"`
Expertise interface{} `json:"expertise"`
Languages interface{} `json:"languages"`
}
response := dto.CreateFilterResponse{
Id: res.Id,
Expertise: Unmarshal(res.Expertise), // ?? not decoding, still json
Languages: Unmarshal(res.Languages), // ?? not decoding, still json
}
非常感謝您的幫助,我需要ExpertiseandLanguages分別是 {} 和 []
這就是我得到的回應:
{"id":5,"expertise":"[{\"role\":1,\"experience\":5},
{\"role\":3,\"experience\":4}]","languages":"[1,2,3]"}
筆記:
專長是 jsonb 列:[]{role: int, experience: int}
語言是 jsonb 列:[]int
uj5u.com熱心網友回復:
感謝@Blackgreen 的評論,這個建議奏效了。
正如他所建議的那樣“我認為問題在于您正在將 jsonb 位元組掃描成字串,這會導致它被逐字解釋。然后當您將字串傳遞給 json.Unmarshal 時,它仍然是一個字串。將專業知識和語言的型別更改為[]位元組(或json.RawMessage)”
我做了同樣的事情,它的作業原理,這里是代碼:
// for parsing jsonb coming from db query
type Result struct {
Id int
Expertise json.RawMessage // change
Languages json.RawMessage // change
}
// the database query itself
e, _ := json.Marshal(filters.Expertise)
l, _ := json.Marshal(filters.Languages)
row := r.db.QueryRow(`
INSERT INTO filters (user_id, expertise, languages)
VALUES ($1, $2, $3)
ON CONFLICT (user_id) DO
UPDATE SET expertise=$2, languages=$3
RETURNING id, expertise, languages;
`, userid, e, l)
var res Result
err := row.Scan(&res.Id, &res.Expertise, &res.Languages) // scanning to result
if err != nil {
fmt.Println("Unable to create a new filter ==>", err)
return nil, err
}
然后,我Unmarshalled將expertise和languages使用一個輔助方法jsonb值,并創建了一個Response客戶端的結構:
// response struct type
type CreateFilterResponse struct {
Id int `json:"id"`
Expertise interface{} `json:"expertise"`
Languages interface{} `json:"languages"`
}
// final response struct
response := dto.CreateFilterResponse{
Id: res.Id,
Expertise: Unmarshal(res.Expertise),
Languages: Unmarshal(res.Languages),
}
// helper method
func Unmarshal(value []byte) interface{} {
var obj interface{}
json.Unmarshal(value, &obj)
return obj
}
這暫時有效。我仍然需要找到一種簡單的方法來執行此操作,因為這是執行簡單任務的太多樣板代碼。 就像在 JS/TS 中一樣,它可以使用單行代碼來完成 JSON.parse(value)
uj5u.com熱心網友回復:
問題出在 json 輸出中。它對您的 JSON 進行了兩次編碼,因此難以讀取和反序列化結構中的 json。
您可以從組織結構開始,如下所示:
type Expertise struct {
Role int `json:"role"`
Experience int `json:"Experience"`
}
type CreateFilterResponse struct {
Id int `json:"id"`
Expert []Expertise `json:"expertise"`
Languages []int `json:"languages"`
}
我做了一個更簡潔的方法只是為了舉例說明和促進理解。它將洗掉不必要的引號和轉義,因此您可以將字串轉換為 []bytes 并解組您的結構。
func jsonCleaner(quoted string) []byte{
quoted = strings.ReplaceAll(quoted, "\n", "")
quoted = strings.ReplaceAll(quoted, "\\", "")
quoted = strings.ReplaceAll(quoted, "]\"", "]")
quoted = strings.ReplaceAll(quoted, "\"[", "[")
dataBytes := []byte(quoted)
fmt.Println(dataBytes)
return dataBytes
}
您的 json 訊息將來自:
{"id":5,"expertise":"[{\"role\":1,\"experience\":5},{\"role\":3,\"experience\":4}]","languages":"[1,2,3]"}
到:
{"id":5,"expertise":[{"role":1,"experience":5},"role":3,"experience":4}],"languages":[1,2,3]}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/408984.html
標籤:
