Golang如何直接将Postgres JSON数据传递到模板?
Golang如何直接将Postgres JSON数据传递到模板? 我可以直接从PostgreSQL获取JSON数据:
SELECT json_agg(hr)::text FROM hr
结果如下:
[map[json_agg:[ {“hr_id”:34,“hr_sign”:“JD”,“hr_job”:“20-0001”,“hr_code”:“PM”,“hr_subject”:“asdf”,“hr_qty”:0.50,“hr_ppu”:1000.00,“hr_sum”:500.00,“hr_date”:“2020-08-22”},
{“hr_id”:35,“hr_sign”:“JD”,“hr_job”:“20-0001”,“hr_code”:“PM”,“hr_subject”:“456”,“hr_qty”:5.25,“hr_ppu”:1000.00,“hr_sum”:5250.00,“hr_date”:“2020-08-22”}]]]
有没有简单的方法可以将这个数据发送到Go模板中?
在另一个讨论中,@Lutzhorn提供的解决方案可能可以作为解决方案的一部分。

Go Playground - The Go Programming Language
我现在想知道,是否有一种自动化的方法可以去掉开头的:
[map[json_agg:
和结尾的:
]]
或者是否有其他方法可以从PostgreSQL获取JSON数据并注入到Go HTML模板中?
更多关于Golang如何直接将Postgres JSON数据传递到模板?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
列 hr 是什么 PostgreSQL 类型?
更多关于Golang如何直接将Postgres JSON数据传递到模板?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我仍然不理解表的结构。
这个
SELECT json_agg(hr)::text
表明使用了 hr。hr 的 PostgreSQL 类型是什么?
你不知道这张表的列吗?为什么要把它们聚合成JSON,然后不得不在Go中再次解析?为什么不直接将列选择到一个匹配的Go结构体中,省去JSON的来回转换呢?
Sibert:
SELECT json_agg(hr)::text
也许这不是从 PostgreSQL 中选择 JSON 以供 Go 使用的最佳方式。
我还没有尝试过,但这看起来很有希望:
也许这不是从 PostgreSQL 中选择 JSON 供 Go 使用的最佳方式。
你能详细说明一下吗?什么方法会更好?
我将其视为从存储过程创建 JSON 输出。在服务器上更快,并且希望在 Go 中进行更少的迭代。你仍然拥有关系数据库管理系统的功能,因为你没有将值存储在 JSON 列中。
{“hr_id”:34,“hr_sign”:“JD”,“hr_job”:“20-0001”,“hr_code”:“PM”,“hr_subject”:“asdf”,“hr_qty”:0.50,“hr_ppu”:1000.00,“hr_sum”:500.00,“hr_date”:“2020-08-22”}
在这个例子中,涉及 int64、varchar、numeric、date 类型的列。它可以是所有类型的列。 除了 json 列 🙂
lutzhorn:
表示使用了
hr。hr的 PostgreSQL 类型是什么?
我对 PostgreSQL 中的 JSON 还不熟悉,但我认为这和 * 的作用差不多。
就像是“创建表 hr 中所有字段的 JSON 聚合”
你可以通过以下方式选择特定的列:
select json_agg((hr_id,hr_date)) from hr
为什么不直接将列选择到匹配的 Go 结构体中,而无需经过 JSON 的往返转换?
因为这个问题:HTML 表格中数值显示为 [53 48 48 46 48 48]
如果对此有解决方法,我将非常高兴。
以下是从 PostgreSQL 获取数据的方式(数值显示为字节切片):
func get(query string) interface{} {
if len(query) > 0 {
var list []map[string]interface{}
rows, err := db.Queryx(query)
if err != nil {
log("get error" + err.Error())
}
defer rows.Close()
for rows.Next() {
row := make(map[string]interface{})
err = rows.MapScan(row)
if err != nil {
log("next " + err.Error())
}
list = append(list, row)
}
rows.Close()
return (list)
}
return nil
}
可以直接将PostgreSQL的JSON数据传递给Go模板,无需手动处理字符串格式。以下是几种方法:
方法1:使用database/sql的RawBytes或string类型
import (
"database/sql"
"encoding/json"
"html/template"
)
func GetJSONData(w http.ResponseWriter, r *http.Request) {
var jsonData string
// 直接从数据库获取JSON字符串
err := db.QueryRow("SELECT json_agg(hr)::text FROM hr").Scan(&jsonData)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// 解析为interface{}以便模板使用
var data interface{}
if err := json.Unmarshal([]byte(jsonData), &data); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
tmpl := template.Must(template.ParseFiles("template.html"))
tmpl.Execute(w, data)
}
方法2:使用json.RawMessage直接传递
func GetJSONDataRaw(w http.ResponseWriter, r *http.Request) {
var rawJSON json.RawMessage
// 使用json.RawMessage直接接收
err := db.QueryRow("SELECT json_agg(hr) FROM hr").Scan(&rawJSON)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// 在模板中作为template.JS使用
tmpl := template.Must(template.ParseFiles("template.html"))
tmpl.Execute(w, map[string]interface{}{
"jsonData": template.JS(rawJSON),
})
}
方法3:使用结构体映射(推荐)
type HRRecord struct {
HRID int `json:"hr_id"`
HRSign string `json:"hr_sign"`
HRJob string `json:"hr_job"`
HRCode string `json:"hr_code"`
HRSubject string `json:"hr_subject"`
HRQty float64 `json:"hr_qty"`
HRPPU float64 `json:"hr_ppu"`
HRSum float64 `json:"hr_sum"`
HRDate string `json:"hr_date"`
}
func GetStructuredData(w http.ResponseWriter, r *http.Request) {
var jsonData []byte
err := db.QueryRow("SELECT json_agg(hr) FROM hr").Scan(&jsonData)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
var records []HRRecord
if err := json.Unmarshal(jsonData, &records); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
tmpl := template.Must(template.ParseFiles("template.html"))
tmpl.Execute(w, records)
}
模板示例(template.html)
<!DOCTYPE html>
<html>
<body>
<!-- 方法1/3:直接遍历结构化数据 -->
{{range .}}
<div>
<p>ID: {{.HRID}}</p>
<p>Job: {{.HRJob}}</p>
<p>Subject: {{.HRSubject}}</p>
<p>Amount: {{.HRSum}}</p>
</div>
{{end}}
<!-- 方法2:作为JavaScript对象使用 -->
<script>
var jsonData = {{.jsonData}};
console.log(jsonData);
// 在客户端直接使用JSON数据
</script>
</body>
</html>
方法4:使用pgx驱动直接获取JSON
import (
"github.com/jackc/pgx/v4"
"github.com/jackc/pgtype"
)
func GetWithPgx(w http.ResponseWriter, r *http.Request) {
conn, _ := pgx.Connect(context.Background(), "postgres://...")
defer conn.Close(context.Background())
var jsonData pgtype.JSON
err := conn.QueryRow(context.Background(),
"SELECT json_agg(hr) FROM hr").Scan(&jsonData)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
var data interface{}
jsonData.AssignTo(&data)
tmpl := template.Must(template.ParseFiles("template.html"))
tmpl.Execute(w, data)
}
最简洁的方法是使用json.RawMessage或直接扫描到string类型,然后通过json.Unmarshal解析。这样可以直接将解析后的Go数据结构传递给模板,无需手动处理字符串格式。

