Golang中JSON与结构体的相互转换及结构体渲染到HTML的实现

Golang中JSON与结构体的相互转换及结构体渲染到HTML的实现 我拥有以下结构体:

	type Data struct {
			Data1         int
			Data2		int
			ImpData     []struct {
				Title          string
				ID               string
				TextS string
			}
		}
		

我将JSON代码解组到变量 o

		var o Data
		err = json.Unmarshal(output, &o)
		if err != nil {
			panic(err.Error())
		}

我使用一个for循环来获取数据

		for i := 0; i < len(o.ImpData); i++ {
				fmt.Printf(" Test: %+v", o.ImpData[i].Title)
				}

到目前为止一切正常,但我不知道如何准确地使用正确的参数和数据来执行模板。

	tmpl, _ := template.ParseFiles("index.html")
	tmpl.Execute(w, o)
	
	
HTML:
<p style="color: black;"> {{ range .ImpData }}  {{ . }}</p>

更多关于Golang中JSON与结构体的相互转换及结构体渲染到HTML的实现的实战教程也可以访问 https://www.itying.com/category-94-b0.html

7 回复

感谢您的回答和帮助。

为什么您要声明两个结构体?这让我非常困惑,因为我有一个结构体嵌套在另一个结构体里。 在我的例子中,解组后的 JSON 数据在变量 o 中。 还有,为什么是 dat.ImpData?我的输出是 o.Impdata[i].Titleo.Impdata[i].TextS 等等,这些需要在 HTML 模板中渲染。

理解这个让我的大脑要栈溢出了 😄

更多关于Golang中JSON与结构体的相互转换及结构体渲染到HTML的实现的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


天啊,它真的可以运行了!非常感谢您付出的时间和提供的帮助!:slight_smile:

最后一个问题,我如何才能在 HTML 中同时渲染结构体中的 Data1Data2 以及 ImpData

另外,假设我有另一个独立的结构体,也想在同一个 HTML 中解析它,这该如何实现?

例如:

type OtherData struct {
	OData1   int
	OData2   int
	BookData []struct {
		Title string
		ID    string
		TextS string
	}
}

我该如何将这个结构体也渲染到同一个 HTML 中呢?

再次感谢 🙂 好的,但如果它没有相同的子记录呢?

像这样

type Data struct {
    Data1         int
    Data2 int
    ImpData     []struct {
        Title          string
        ID               string
        TextS string
        }
    }

type OtherData struct {
    OData1   int
    OData2   int
    BookData []struct {
        Name string
        ID    string
        Location string
    }
}

我如何在同一份渲染的HTML中获取这两份数据?

还有另一件事:

我是不是需要对Data做类似这样的操作?

dat.ImpData = append(dat.ImpData etc

但这只是ImpData的数据,而不是Data的全部数据,对吗? 所以我的理解是,我也需要追加它?

Babtus2:

最后一个问题,我如何才能在HTML中同时渲染结构体中的Data1、Data2以及ImpData?

试试这个模板:

var htmlTmpl = `<h1>Data: {{ .Data1 }}</h1>
{{ range .ImpData }}
    <p style="color: black;">{{ .Title }}</p>
{{ end }}`

Babtus2:

假设我有另一个独立的结构体,也想在同一个HTML中解析它,这该如何实现?

如果你有类似的数据,我建议创建一个能涵盖这两个概念的类型/结构体。这两个子记录在那个结构体上都有Title、ID和TextS,对吧?所以你可以把它提取到它自己的结构体中:

type LineItem struct {
	Title string
	ID    string
	TextS string
}
type Data struct {
	Data1   int
	Data2   int
	ImpData []LineItem 
}
type OtherData struct {
	OData1   int
	OData2   int
	BookData []LineItem 
}

这样,DataOtherData 都有一个 LineItem 类型的切片。大致就是这样的思路。

为什么你要声明两个结构体?这让我非常困惑,因为我有一个结构体嵌套在另一个结构体里。

Data 包含一个 ImpData 类型的切片,而不是一个匿名结构体。我之所以这样做,是因为当你像下面这样将子结构体声明为匿名结构体时:

type Data struct {
	Data1   int
	Data2   int
	ImpData []struct { // 这是什么类型?
		Title string
		ID    string
		TextS string
	}
}

…这会使得我构造的数据初始化过程变得更加冗长:

for i := 0; i < 10; i++ {
	dat.ImpData = append(dat.ImpData, struct {
		Title string
		ID    string
		TextS string
	}{"test", strconv.Itoa(i), "test"})
}

但实际上效果是一样的。你可以在这里运行它,使用与你示例中完全相同的 Data 结构体:

Go Playground - The Go Programming Language

尝试将你的模板切换成类似这样的:

{{ range .ImpData }}
    <p style="color: black;">{{ .Title }}</p>
{{ end }}

这里有一个完整的示例,可以帮助你开始:

package main

import (
	"html/template"
	"os"
	"strconv"
)

type ImpData struct {
	Title string
	ID    string
	TextS string
}

type Data struct {
	Data1   int
	Data2   int
	ImpData []ImpData
}

var htmlTmpl = `{{ range .ImpData }}
    <p style="color: black;">{{ .Title }}</p>
{{ end }}`

func main() {
	// 为了简洁忽略错误。实际中不要这样做。
	t := template.Must(template.New("test").Parse(htmlTmpl))
	dat := Data{}
	for i := 0; i < 10; i++ {
		dat.ImpData = append(dat.ImpData, ImpData{Title: "test", ID: strconv.Itoa(i), TextS: "test"})
	}
	t.Execute(os.Stdout, dat)
}

你可以在 Go Playground 上运行它:

Go Playground - The Go Programming Language

在Golang中实现JSON与结构体的相互转换及模板渲染,以下是完整的实现方案:

1. JSON与结构体转换

结构体定义优化(添加JSON标签)

type Data struct {
    Data1   int `json:"data1"`
    Data2   int `json:"data2"`
    ImpData []ImpItem `json:"impData"`
}

type ImpItem struct {
    Title  string `json:"title"`
    ID     string `json:"id"`
    TextS  string `json:"textS"`
}

JSON反序列化

var o Data
err := json.Unmarshal(output, &o)
if err != nil {
    log.Fatal("JSON解析错误:", err)
}

JSON序列化

// 结构体转JSON
jsonData, err := json.Marshal(o)
if err != nil {
    log.Fatal("JSON编码错误:", err)
}

// 格式化输出
jsonIndent, _ := json.MarshalIndent(o, "", "  ")
fmt.Println(string(jsonIndent))

2. 模板渲染实现

Go模板处理

func handler(w http.ResponseWriter, r *http.Request) {
    // 解析模板
    tmpl, err := template.ParseFiles("index.html")
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    
    // 准备数据
    data := Data{
        Data1: 100,
        Data2: 200,
        ImpData: []ImpItem{
            {Title: "标题1", ID: "001", TextS: "内容1"},
            {Title: "标题2", ID: "002", TextS: "内容2"},
        },
    }
    
    // 执行模板渲染
    err = tmpl.Execute(w, data)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

HTML模板示例 (index.html)

<!DOCTYPE html>
<html>
<head>
    <title>数据展示</title>
</head>
<body>
    <h1>基础数据</h1>
    <p>Data1: {{.Data1}}</p>
    <p>Data2: {{.Data2}}</p>
    
    <h1>重要数据列表</h1>
    {{range .ImpData}}
    <div style="border: 1px solid #ccc; padding: 10px; margin: 10px;">
        <h3 style="color: black;">{{.Title}}</h3>
        <p><strong>ID:</strong> {{.ID}}</p>
        <p><strong>内容:</strong> {{.TextS}}</p>
    </div>
    {{else}}
    <p>暂无数据</p>
    {{end}}
</body>
</html>

3. 完整HTTP服务器示例

package main

import (
    "encoding/json"
    "html/template"
    "log"
    "net/http"
)

type Data struct {
    Data1   int      `json:"data1"`
    Data2   int      `json:"data2"`
    ImpData []ImpItem `json:"impData"`
}

type ImpItem struct {
    Title string `json:"title"`
    ID    string `json:"id"`
    TextS string `json:"textS"`
}

func main() {
    http.HandleFunc("/", renderTemplate)
    log.Println("服务器启动在 :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

func renderTemplate(w http.ResponseWriter, r *http.Request) {
    // 模拟JSON数据
    jsonStr := `{
        "data1": 100,
        "data2": 200,
        "impData": [
            {"title": "项目A", "id": "001", "textS": "这是项目A的描述"},
            {"title": "项目B", "id": "002", "textS": "这是项目B的描述"}
        ]
    }`
    
    var o Data
    err := json.Unmarshal([]byte(jsonStr), &o)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    
    // 解析并执行模板
    tmpl, err := template.ParseFiles("index.html")
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    
    err = tmpl.Execute(w, o)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

4. 模板函数扩展

// 自定义模板函数
funcMap := template.FuncMap{
    "upper": strings.ToUpper,
    "add": func(a, b int) int { return a + b },
}

tmpl := template.New("index.html").Funcs(funcMap)
tmpl, _ = tmpl.ParseFiles("index.html")

// 在HTML中使用自定义函数
{{range .ImpData}}
<p>{{.Title | upper}}</p>
<p>计算值: {{add .Data1 .Data2}}</p>
{{end}}

这个实现方案提供了完整的JSON与结构体转换、模板渲染的示例,可以直接运行并查看结果。

回到顶部