Golang如何将JSON数据嵌入HTML模板?

Golang如何将JSON数据嵌入HTML模板? 我尝试将菜单存储在数据库中,并用它来填充Go HTML模板。我已经成功获取了JSON数据并独立完成了Go HTML模板的填充。但是,如何将JSON数据从 func main 传递到模板函数 func page 中呢?

package main

import (
    "encoding/json"
    "fmt"
    "html/template"
    "io/ioutil"
    "net/http"
    "os"
)

func main() {
    resp, err := http.Get("https://api3.go4webdev.org/menu/all")
    if err != nil {
        fmt.Println("No response")
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body)) // 如何将此传递给 "func page" 并填充菜单?
    page()
}

func page() {
    fmt.Println()
    t := template.Must(template.New("").Parse(templ))

    m := map[string]interface{}{}
    if err := json.Unmarshal([]byte(jsondata), &m); err != nil {
        panic(err)
    }

    if err := t.Execute(os.Stdout, m); err != nil {
        panic(err)
    }
}

const templ = `
<html><body>
   <ul>
     <li id={{.menu_id}}>{{.menu_txt}}</li>
     <li id={{.menu_id}}>{{.menu_txt}}</li>
   </ul>
</body></html>`

const jsondata = `{"menu_id":"1", "menu_txt": "Home"}`

结果将是这样的:

[{"menu_icn":"","menu_id":"code","menu_lnk":"/code","menu_main":"code","menu_sort":1,"menu_txt":"Code Philosophy"},{"menu_icn":"","menu_id":"home","menu_lnk":"/home","menu_main":"home","menu_sort":1,"menu_txt":"Navigation”}, etc…]

<html><body>
   <ul>
     <li id=1>Home</li>
     <li id=1>Home</li>
   </ul>
</body>

当我尝试将JSON数据传递到 func page(jsondata) 时…

...
	page(string(body))
}

func page(jsondata) {
....

…我遇到了一些错误

./main.go:23:11: undefined: jsondata ./main.go:28:34: undefined: jsondata

如果我在jsondata后面加上string

	page(string(body))
}

func page(jsondata string) {

我得到了这些错误:

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


更多关于Golang如何将JSON数据嵌入HTML模板?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

12 回复

Go Playground - The Go Programming Language

更多关于Golang如何将JSON数据嵌入HTML模板?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


是的,[]map[string]interface{}[]interface{} 更具体一些,这应该会使访问数据的代码更简单。

func main() {
    fmt.Println("hello world")
}

错误信息已经说明了问题所在。你正试图将一个 JSON 数组反序列化到一个 map 中。我之前告诉过你并且展示过,你可以将一个 JSON 数组反序列化到一个切片中。如果你的 JSON 是一个对象,那么你可以将其反序列化到一个 map 中。你需要对 JSON 的结构有一定的理解。

Go Playground - The Go Programming Language

json: 无法将数组反序列化为 Go 值,其类型为 map[string]interface {}

据我所见,这不起作用?

无法将数组反序列化为 Go 类型 map[string]interface {}

你可以将 JSON 数组反序列化为 Go 的 []interface{},或者将 JSON 对象反序列化为 Go 的 map[string]interface{}。更好的做法是使用与你的 JSON 结构模式匹配的更具体的 Go 类型。

经过一番搜索,我找到了一个解决方案:

var m []map[string]interface{}

Go Playground - The Go Programming Language

Go Playground - The Go Programming Language

你需要对JSON的结构有一定的理解。

我确实理解JSON的结构。但在Go中读写JSON的语义和语法让我感到困惑。

举个例子,这让我很困惑:

m := []map[string]interface{}

// 这行不通 但是

var m []map[string]interface{}

// 这行得通

你可以将JSON数组解组到Go的[]interface{}中,或者将JSON对象解组到Go的map[string]interface{}中。

	m := map[string]interface{}{}
	if err := json.Unmarshal([]interface(jsondata), &m); err != nil {
		panic(err)
	}

语法错误:意外的 (,期望的是 {

或者你的意思是?

m := []map[string]interface{} 为变量 m 分配了一个类型,因为右侧是一个 map 切片类型,而不是一个值。 var m []map[string]interface{} 声明变量 m 为某个类型(map 切片类型)。它会被隐式初始化为该类型的零值。 := 是声明并初始化变量的简写形式。变量的值将被设置为右侧的值,其类型将从右侧的类型推断出来。Go 语言之旅

在使用 json.Unmarshal 时,无需初始化变量,因为 Unmarshal 会设置变量的值。

你好 Sibert, 你能将请求体作为 []byte 发送吗? 这样你就不需要将数据转换两次了。

package main

import (
	"encoding/json"
	"fmt"
	"html/template"
	"io"
	"net/http"
	"os"
)

func main() {
	resp, err := http.Get("https://api3.go4webdev.org/menu/all")
	if err != nil {
		fmt.Println("No response")
	}
	defer resp.Body.Close()
	body, err := io.ReadAll(resp.Body)
	fmt.Println(string(body)) // 如何将此传递给 "func page" 并填充菜单?
	page(body)
}

func page(jsondata []byte) {
	fmt.Println()
	t := template.Must(template.New("").Parse(templ))

	m := map[string]interface{}{}
	if err := json.Unmarshal([]byte(jsondata), &m); err != nil {
		panic(err)
	}

	if err := t.Execute(os.Stdout, m); err != nil {
		panic(err)
	}
}

const templ = `
<html><body>
   <ul>
     <li id={{.menu_id}}>{{.menu_txt}}</li>
     <li id={{.menu_id}}>{{.menu_txt}}</li>
   </ul>
</body></html>`

你能将请求体以 []byte 的形式发送吗?

你的代码给出了这个错误:

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

JSON 在我的 API 和外部 API 中都是一个非常通用的标准。所以我想我必须学习如何处理 JSON。我该如何对数据进行两次转换?

这里有一个不涉及 API 的示例。错误和之前一样:

package main

import (
	"encoding/json"
	"html/template"
	"os"
)

func main() {
	t := template.Must(template.New("").Parse(templ))

	m := map[string]interface{}{}
	if err := json.Unmarshal([]byte(jsondata), &m); err != nil {
		panic(err)
	}

	if err := t.Execute(os.Stdout, m); err != nil {
		panic(err)
	}
}

const templ = `
<html><body>
{{ range . }}
   <li id={{.menu_id}}> {{ .menu_txt }}</li>
{{ end }}
</body></html>`

const jsondata = `[{"menu_id":"1", "menu_txt": "Home"},{"menu_id":"2", "menu_txt": "Prefs"}]`

Go Playground - The Go Programming Language

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

在Go中传递JSON数据到模板函数时,需要正确处理函数参数和JSON结构。以下是修改后的代码:

package main

import (
    "encoding/json"
    "fmt"
    "html/template"
    "io/ioutil"
    "net/http"
    "os"
)

func main() {
    resp, err := http.Get("https://api3.go4webdev.org/menu/all")
    if err != nil {
        fmt.Println("No response")
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }
    
    // 传递JSON数据到page函数
    page(string(body))
}

func page(jsondata string) {
    t := template.Must(template.New("").Parse(templ))

    // 根据JSON结构选择正确的解析方式
    var data []map[string]interface{}
    if err := json.Unmarshal([]byte(jsondata), &data); err != nil {
        panic(err)
    }

    // 传递数据到模板
    if err := t.Execute(os.Stdout, data); err != nil {
        panic(err)
    }
}

const templ = `
<html><body>
   <ul>
   {{range .}}
     <li id="{{.menu_id}}">{{.menu_txt}}</li>
   {{end}}
   </ul>
</body></html>`

如果JSON是单个对象而不是数组,使用以下模板:

const templ = `
<html><body>
   <ul>
     <li id="{{.menu_id}}">{{.menu_txt}}</li>
   </ul>
</body></html>`

对应的page函数修改:

func page(jsondata string) {
    t := template.Must(template.New("").Parse(templ))

    var data map[string]interface{}
    if err := json.Unmarshal([]byte(jsondata), &data); err != nil {
        panic(err)
    }

    if err := t.Execute(os.Stdout, data); err != nil {
        panic(err)
    }
}

对于更复杂的模板处理,可以使用自定义结构体:

type MenuItem struct {
    MenuID   string `json:"menu_id"`
    MenuTxt  string `json:"menu_txt"`
    MenuLnk  string `json:"menu_lnk"`
    MenuIcn  string `json:"menu_icn"`
    MenuMain string `json:"menu_main"`
    MenuSort int    `json:"menu_sort"`
}

func page(jsondata string) {
    t := template.Must(template.New("").Parse(templ))

    var menuItems []MenuItem
    if err := json.Unmarshal([]byte(jsondata), &menuItems); err != nil {
        panic(err)
    }

    if err := t.Execute(os.Stdout, menuItems); err != nil {
        panic(err)
    }
}

const templ = `
<html><body>
   <ul>
   {{range .}}
     <li id="{{.MenuID}}">
         <a href="{{.MenuLnk}}">{{.MenuTxt}}</a>
     </li>
   {{end}}
   </ul>
</body></html>`
回到顶部