How to send an array of maps and iterate over it using gin-templating

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

How to send an array of maps and iterate over it using gin-templating

问题

以下是一段工作代码的片段。我正在使用gin模板引擎。

c.HTML(200, "index", gin.H{
    "title": "Welcome",
    "students": map[int]map[string]string{1: {"PID": "1", "Name": "myName"}},
})

在index模板中,我有以下内容:

<TABLE class="myTable">
    <tr class="headingTr">
        <td>Name</td>
    </tr>
    {{range $student := .students}}
    <td>{{$student.Name}}</td>
    {{end}}
</TABLE>

如你所见,我在标题(map)中硬编码了students的值。我希望从我构建的REST API中获取这些数据。我的REST API的响应是一个数组:

[
  {
    "id": 1,
    "name": "Mary"
  },
  {
    "id": 2,
    "name": "John"
  }
]

我可以将这个JSON响应解组为map[string]string,而不是map[int]map[string]string。我该如何将这个解组后的数据作为students的参数值,并在index模板中对这个数组进行迭代?

英文:

Following is the snippet of a working code. I am using gin templating engine.

c.HTML(200, &quot;index&quot;, gin.H{
			&quot;title&quot;:    &quot;Welcome&quot;,
			&quot;students&quot;: map[int]map[string]string{1: {&quot;PID&quot;: &quot;1&quot;, &quot;Name&quot;: &quot;myName&quot;}},})

And in index template I have:

 &lt;TABLE class= &quot;myTable&quot; &gt;
        &lt;tr class=&quot;headingTr&quot;&gt;
            &lt;td&gt;Name&lt;/td&gt;
        &lt;/tr&gt;
        {{range $student := .students}}
        &lt;td&gt;{{$student.Name}}&lt;/td&gt;                    
        {{end}}
 &lt;/TABLE&gt;

As you can see I have hard-coded the value of students on the headers (the map). I want to have this data from a rest API that I have built. the response of my rest API is an array:

 [
  {
    &quot;id&quot;: 1,
    &quot;name&quot;: &quot;Mary&quot;
  },
  {
    &quot;id&quot;: 2,
    &quot;name&quot;: &quot;John&quot;
  }
]

I can unmarshal this JSON response into map[string]string instead of map[int]map[string]string. How can pass this unmarhsaled body in parameter value for students and then iterate over this array the index template?

答案1

得分: 1

使用结构体

你现在有一个JSON数组,将其解组为Go切片。建议创建一个Student结构体来模拟你的学生,以便编写干净和明确的Go代码。

在模板中,{{range}}操作将点号.设置为当前元素,你可以在{{range}}体内直接使用点号.来引用它,所以学生的姓名将是.Name

以下是可运行的代码(在Go Playground上尝试):

func main() {
    t := template.Must(template.New("").Parse(templ))
    var students []Student
    if err := json.Unmarshal([]byte(jsondata), &students); err != nil {
        panic(err)
    }
    params := map[string]interface{}{"Students": students}
    if err := t.Execute(os.Stdout, params); err != nil {
        panic(nil)
    }
}

const jsondata = `[
  {
    "id": 1,
    "name": "Mary"
  },
  {
    "id": 2,
    "name": "John"
  }
]`

const templ = `<TABLE class="myTable">
        <tr class="headingTr">
            <td>Name</td>
        </tr>
        {{range .Students}}
        <td>{{.Name}}</td>                    
        {{end}}
 </TABLE>`

输出结果:

<TABLE class="myTable">
        <tr class="headingTr">
            <td>Name</td>
        </tr>
    
        <td>Mary</td>                    
    
        <td>John</td>                    
    
 </TABLE>

使用映射

如果你不想创建和使用Student结构体,你仍然可以使用一个简单的映射,其类型为map[string]interface{},它可以表示任何JSON对象。但是要知道,在这种情况下,你必须将学生的姓名引用为.name,因为它在JSON文本中是这样出现的,因此小写的"name"键将在解组后的Go映射中使用:

func main() {
    t := template.Must(template.New("").Parse(templ))
    var students []map[string]interface{}
    if err := json.Unmarshal([]byte(jsondata), &students); err != nil {
        panic(err)
    }
    params := map[string]interface{}{"Students": students}
    if err := t.Execute(os.Stdout, params); err != nil {
        panic(nil)
    }
}

const templ = `<TABLE class="myTable">
        <tr class="headingTr">
            <td>Name</td>
        </tr>
        {{range .Students}}
        <td>{{.name}}</td>                    
        {{end}}
 </TABLE>`

输出结果与前面相同。在Go Playground上尝试这个变体。

英文:

With a struct

What you have is a JSON array, unmarshal it into a Go slice. Recommended to create a Student struct to model your students to have a clean and conscious Go code.

And in the template the {{range}} action sets the dot . to the current element, you can refer to it inside the {{range}} body simply as the dot ., so the student name will be .Name.

Working code (try it on the Go Playground):

func main() {
	t := template.Must(template.New(&quot;&quot;).Parse(templ))
	var students []Student
	if err := json.Unmarshal([]byte(jsondata), &amp;students); err != nil {
		panic(err)
	}
	params := map[string]interface{}{&quot;Students&quot;: students}
	if err := t.Execute(os.Stdout, params); err != nil {
		panic(nil)
	}
}

const jsondata = `[
  {
    &quot;id&quot;: 1,
    &quot;name&quot;: &quot;Mary&quot;
  },
  {
    &quot;id&quot;: 2,
    &quot;name&quot;: &quot;John&quot;
  }
]`

const templ = `&lt;TABLE class= &quot;myTable&quot; &gt;
        &lt;tr class=&quot;headingTr&quot;&gt;
            &lt;td&gt;Name&lt;/td&gt;
        &lt;/tr&gt;
        {{range .Students}}
        &lt;td&gt;{{.Name}}&lt;/td&gt;                    
        {{end}}
 &lt;/TABLE&gt;`

Output:

&lt;TABLE class= &quot;myTable&quot; &gt;
        &lt;tr class=&quot;headingTr&quot;&gt;
            &lt;td&gt;Name&lt;/td&gt;
        &lt;/tr&gt;
    
        &lt;td&gt;Mary&lt;/td&gt;                    
    
        &lt;td&gt;John&lt;/td&gt;                    
    
 &lt;/TABLE&gt;

With a map

If you don't want to create and use a Student struct, you can still do it with a simple map whose type is map[string]interface{} which can represent any JSON object, but know that in this case you have to refer to students' names as .name as that is how it appears in the JSON text, and so lowercased &quot;name&quot; key will be used in the unmarshaled Go map:

func main() {
	t := template.Must(template.New(&quot;&quot;).Parse(templ))
	var students []map[string]interface{}
	if err := json.Unmarshal([]byte(jsondata), &amp;students); err != nil {
		panic(err)
	}
	params := map[string]interface{}{&quot;Students&quot;: students}
	if err := t.Execute(os.Stdout, params); err != nil {
		panic(nil)
	}
}

const templ = `&lt;TABLE class= &quot;myTable&quot; &gt;
        &lt;tr class=&quot;headingTr&quot;&gt;
            &lt;td&gt;Name&lt;/td&gt;
        &lt;/tr&gt;
        {{range .Students}}
        &lt;td&gt;{{.name}}&lt;/td&gt;                    
        {{end}}
 &lt;/TABLE&gt;`

Output is the same. Try this variant on the Go Playground.

huangapple
  • 本文由 发表于 2016年8月23日 16:40:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/39096335.html
匿名

发表评论

匿名网友

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

确定