如何在Golang中将多个数据对象传递给HTML模板?

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

How to pass multiple data objects to HTML templates in Golang

问题

我正在将表的所有行作为JSON返回给变量pdata,并将其解组为接口对象。
我有一个用户结构体的实例,我想将其与解组后的JSON数据一起传递给渲染函数,并在HTML模板中使用字段参数{{.fieldname}}来访问它。

if uuid != "" {
    pdata, err := getProduct()
    if err != nil {
        fmt.Println(err)
    }

    type Prdata struct {
        Puid     string `json:"puid"`
        Pname    string `json:"pname"`
        Quantity string `json:"quantity"`
        Price    string `json:"price"`
        Image    string `json:"image"`
    }

    var Pr Prdata

    err = json.Unmarshal(pdata, &Pr)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Println(string(pdata))
    fmt.Println(Pr)
    fmt.Println(u)

    render(w, "internal", Pr)
}

fmt.Println(string(pdata)) 输出如下:

[{"image":"1Appleiphone7.jpeg","pname":"iphone7","price":"70000","puid":"d6742e4e-2ad6-43c5-97f4-e8a7b00684e2","quantity":"100"}]

我只能成功地将数据解组为interface{}对象。尝试使用键类型为interface{}和值类型为string的映射,但会抛出错误:

json: cannot unmarshal array into Go value of type map[interface{}]string

渲染函数接受类型为interface{}的参数:

func render(w http.ResponseWriter, name string, data interface{})

fmt.Println(Pr) 输出如下:

[map[quantity:100 image:1Appleiphone7.jpeg pname:iphone7 price:70000 puid:d6742e4e-2ad6-43c5-97f4-e8a7b00684e2]]

uUser 结构体的实例:

var u = &User{}

type User struct {
    Uuid     string
    Username string
    Password string
    Fname    string
    Email    string
}

我可以使用管道{{.}}在HTML页面上看到输出。但是我无法使用字段名访问任何数据。

肯定有一种方法可以做到这一点。但我不确定如何做?

当我传递以下类型的JSON时,我可以将其传递给结构体类型,并在模板中使用管道通过键值引用它。

str := `{
    "image": "1Appleiphone7.jpeg",
    "pname": "iphone7",
    "price": "70000",
    "puid": "d6742e4e-2ad6-43c5-97f4-e8a7b00684e2",
    "quantity": "100"
}`

err = json.Unmarshal([]byte(str), &Pr)

数据库记录pdata和上面的str的JSON数据之间的区别在于使用了反引号"`"。尽管JSON数据显示键值对,但实际上它是一个JSON数组而不是JSON对象。有没有办法解决这个问题?

英文:

I am returing all rows of a table as json to the variable pdata and unmarshaling it into an interface object.
I have an instance of the user struct which I would like to pass along with the unmarshalled json data to the render function and access it using field arguments {{.fieldname}} in the html template.

if uuid != "" {
	pdata, err := getProduct()
	if err != nil {
		fmt.Println(err)
	} 

	type Prdata struct {
		Puid     string `json:"puid"`
		Pname    string `json:"pname"`
		Quantity string `json:"quantity"`
		Price    string `json:"price"`
		Image    string `json:"image"`
	}
		
	// Obj:= make(map[Prdata]string)
	
    var Pr Prdata
		 
	err = json.Unmarshal(pdata , &Pr)
	if err != nil {
		fmt.Println(err)
	}
	
	fmt.Println(string(pdata))
	fmt.Println(Pr)
	fmt.Println(u)
		
	render(w, "internal", Pr)
}

fmt.Println(string(pdata)) gives this output

>[{"image":"1Appleiphone7.jpeg","pname":"iphone7","price":"70000","puid":"d6742e4e-2ad6-43c5-97f4-e8a7b00684e2","quantity":"100"}]

I have only been successful to unmarshal the data into an interface{} object. Trying to make maps with keys of the type interface{} and values of type string but it throws the error:
> "json: cannot unmarshal array into Go value of type map[interface {}]string"

The render function takes an argument of the type interface{}

func render(w http.ResponseWriter, name string, data interface{})

fmt.Println(Pr) gives this output:

> [map[quantity:100 image:1Appleiphone7.jpeg pname:iphone7 price:70000 puid:d6742e4e-2ad6-43c5-97f4-e8a7b00684e2]]

u is an instance of struct User

var u = &User{}

type User struct {
	Uuid     string            
	Username string           
	Password string           
	Fname    string            
	Email    string            
}

I can see the output on the html page using the pipeline {{.}}. However I am not able to access any data using the fieldname.

There must be a way of doing this. But I am not sure how?

When I pass of a json of the type below, I am able to pass it to the struct type and reference it by the key values using pipelines in my template.

	str := `{
	"image": "1Appleiphone7.jpeg",
	"pname": "iphone7",
	"price": "70000",
	"puid": "d6742e4e-2ad6-43c5-97f4-e8a7b00684e2",
	"quantity": "100"
	}`

unmarshal function

err = json.Unmarshal([]byte(str), &Pr)

The difference in the json data of the DB record pdata and the one above str is in the use of backticks "`". It seems that though the json data shows key value pairs, it is actually a json array and not a json object. Is there a way to get around this?

答案1

得分: 0

你不需要一个map[interface{}]string来解析JSON对象。你的JSON等同于一个包含多个map的切片:

[
    {
        "image":"1Appleiphone7.jpeg",
        "pname":"iphone7",
        "price":"70000",
        "puid":"d6742e4e-2ad6-43c5-97f4-e8a7b00684e2",
        "quantity":"100"
    }
]

要解析的对象应该是一个具有字符串键和值的map切片:

var Pr []map[string]string

此外,我相信有一个误解:

render函数接受一个interface{}类型的参数

我的意思不是你必须在那里传递一个interface{}类型的变量,而是你可以传递任何类型的变量render函数。

Playground链接

英文:

You don't need a map[interface{}]string to unmarshal the json obj. Your json is equivalent to slice of maps:

[
    {
        "image":"1Appleiphone7.jpeg",
        "pname":"iphone7",
        "price":"70000",
        "puid":"d6742e4e-2ad6-43c5-97f4-e8a7b00684e2",
        "quantity":"100"
    }
]

The object to unmarshal should be a slice of maps with string keys and values:

var Pr []map[string]string

Playground

BTW, I believe misunderstanding is hidden there:

> The render function takes an argument of the type interface{}

I means not that you must pass a variable of interface{} type there but it means you CAN pass a variable of any type to render function.

答案2

得分: 0

我正在发布一个工作示例,将以字节形式解组 JSON 数据到结构体类型中,然后可以在模板中使用 {{.}} 引用。

package main

import (
	"encoding/json"
	"fmt"
)

type Usrdata struct {
	Uuid  string
	Fname string
}

type Prdata struct {
	Puid     string `json:"puid"`
	Pname    string `json:"pname"`
	Quantity string `json:"quantity"`
	Price    string `json:"price"`
	Image    string `json:"image"`
}

type Data struct {
	U Usrdata
	P []Prdata
}

func main() {
	Ur := Usrdata{Uuid: "xyz", Fname: "Somename"}
	Pr := make([]Prdata, 0)
	var Dt Data
	Dt.U = Ur
	pdata := `[{"image":"1Appleiphone7.jpeg","pname":"iphone7","price":"70000","puid":"d6742e4e-2ad6-43c5-97f4-e8a7b00684e2","quantity":"100"}]`
	err := json.Unmarshal([]byte(pdata), &Pr)
	if err != nil {
		fmt.Println(err)
	}
	Dt.P = Pr
	fmt.Println(Pr[0].Pname)
	fmt.Println(Pr)
	fmt.Println(Dt)
}

这段代码将 JSON 数据解组到了相应的结构体类型中,并打印了一些结果。

英文:

I am posting a working example of unmarshalling json as bytes into a struct type which then can be referenced using the {{.}} in the template.

package main

import (
	"encoding/json"
	"fmt"
)

type Usrdata struct {
	Uuid  string
	Fname string
}

type Prdata struct {
	Puid     string `json:"puid"`
	Pname    string `json:"pname"`
	Quantity string `json:"quantity"`
	Price    string `json:"price"`
	Image    string `json:"image"`
}

type Data struct {
	U Usrdata
	P []Prdata
}

func main() {
	Ur := Usrdata{Uuid: "xyz", Fname: "Somename"}
	Pr := make([]Prdata, 0)
	var Dt Data
	Dt.U = Ur
	pdata := `[{"image":"1Appleiphone7.jpeg","pname":"iphone7","price":"70000","puid":"d6742e4e-2ad6-43c5-97f4-e8a7b00684e2","quantity":"100"}]`
	err := json.Unmarshal([]byte(pdata), &Pr)
	if err != nil {
		fmt.Println(err)
	}
	Dt.P = Pr
	fmt.Println(Pr[0].Pname)
	fmt.Println(Pr)
	fmt.Println(Dt)
}

huangapple
  • 本文由 发表于 2017年2月1日 17:01:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/41975647.html
匿名

发表评论

匿名网友

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

确定