golang模板与json的应用

//前端传到后端的模板json格式是`{"uid":"{{tojson .uid}}"}`,这样前端可以用json来显示给用户,但后端用模板替换的时候就会带双引号,如果赋值复杂类型就更麻烦,用以下方法可以解决,python 的jinja2也可以实现类似的功能,并且jinja2提供tojson函数,所以python不需要定义自己的函数

package main


import (

    "bytes"

    "encoding/json"

    fmt "fmt"

    "text/template"

)

var m_d547a4e3_params = make(map[string]interface{})

func doTemplate(body string, m map[string]interface{}) string {

    funcs := template.FuncMap{

        "tojson": func(v interface{}) string {

            a, _ := json.Marshal(v)

            return string(a)

        },

    }

    t := template.New("test").Funcs(funcs)

    t.Delims("\"{{", "}}\"")

    t.Parse(body)

    var tpl bytes.Buffer

    t.Execute(&tpl, m)

    return tpl.String()

}

func main() {

    var arr = [...]string{"wq", "21"}

    fmt.Println(arr[0])

    var i int = 2

    fmt.Println(i)

    m_d547a4e3_params["uid"] = "{\"wq\",\"21\"}"

    m_d547a4e3_params["uid"] = "10"

    m_d547a4e3_params["uid"] = 10

    m_d547a4e3_params["uid"] = arr

    fmt.Println(doTemplate(`{"uid":"{{tojson .uid}}"}`, m_d547a4e3_params))

}







/*python版本

import os, jinja2

json = u'''{

"a":"{{ age | tojson}}"

}'''

_t = jinja2.Template(json, trim_blocks=True, variable_start_string='"{{', variable_end_string='}}"')

_text = _t.render(age={"a":1})

_text = _text.encode('utf-8')

print(_text)

*/

 

已标记关键词 清除标记
<div class="post-text" itemprop="text"> <p>I am looping through my API response and adding it to the html template like this,</p> <pre><code> // Following sends same information as above to the browser as html t, err := template.New("TopMovies").Parse(` {{define "TopMovies"}} <html> <ul> {{$ImgUrl := "http://image.tmdb.org/t/p/w185" }} {{range $movies := .Results}} <li>{{$ImgUrl}}{{$movies.PosterPath}}</li> <li>{{$movies.Adult}}</li> <li>{{$movies.Overview}}</li> <li>{{$movies.ReleaseDate}}</li> <li>{{$movies.GenreIds}}</li> <li>{{$movies.Id}}</li> <li>{{$movies.OriginalTitle}}</li> <li>{{$movies.OriginalLanguage}}</li> <li>{{$movies.Title}}</li> <li>{{$ImgUrl}}{{$movies.BackdropPath}}</li> <li>{{$movies.Popularity}}</li> <li>{{$movies.VoteCount}}</li> <li>{{$movies.Video}}</li> <li>{{$movies.VoteAverage}}</li> {{end}} </ul> </html> {{end}} `) err = t.ExecuteTemplate(w, "T", p) // This writes the client response } </code></pre> <p>I am under the impression I should be able to call this in my html templates like this,</p> <pre><code>{{.TopMovies}} </code></pre> <p>But when I run the app the data does not appear in the html page I am calling it in. What am I missing here?</p> <p>I create a struct like this,</p> <pre><code>//A Page structure type Page struct { Title string TopMovies string } </code></pre> <p>Then I create my handle like this,</p> <pre><code>func TopMoviesHandler(w http.ResponseWriter, r *http.Request) { res, err := http.Get(url) if err != nil { panic(err) } defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { panic(err) } var p Payload err = json.Unmarshal(body, &p) if err != nil { panic(err) } // Following sends same information as above to the browser as html t, err := template.New("TopMovies").Parse(` {{define "TopMovies"}} <html> <ul> {{$ImgUrl := "http://image.tmdb.org/t/p/w185" }} {{range $movies := .Results}} <li>{{$ImgUrl}}{{$movies.PosterPath}}</li> <li>{{$movies.Adult}}</li> <li>{{$movies.Overview}}</li> <li>{{$movies.ReleaseDate}}</li> <li>{{$movies.GenreIds}}</li> <li>{{$movies.Id}}</li> <li>{{$movies.OriginalTitle}}</li> <li>{{$movies.OriginalLanguage}}</li> <li>{{$movies.Title}}</li> <li>{{$ImgUrl}}{{$movies.BackdropPath}}</li> <li>{{$movies.Popularity}}</li> <li>{{$movies.VoteCount}}</li> <li>{{$movies.Video}}</li> <li>{{$movies.VoteAverage}}</li> {{end}} </ul> </html> {{end}} `) err = t.ExecuteTemplate(w, "T", p) // This writes the client response } </code></pre> <p>Then in <code>main.go</code></p> <pre><code> http.HandleFunc("/TopPicks", TopMoviesHandler) TopPicks.html {{define "TopPicks"}} {{template "header" .}} <div class="content"> {{.TopMovies}} </div> {{template "footer" .}} {{end}} </code></pre> <p>What does work is this,</p> <pre><code>func aboutHandler(w http.ResponseWriter, r *http.Request) { display(w, "about", &Page{Title: "About"}) } </code></pre> <p>I can add a title to the page in the same way as I previously mentioned but using <code>display()</code></p> <p>And in the html template</p> <pre><code><title>{{.Title}}</title> </code></pre> <p>How can I make this work for my json response?</p> </div>
<div class="post-text" itemprop="text"> <p>I'm using Gorilla Websocket to update some HTML (img src, text, etc); I do this the following way:</p> <pre><code>mt, message, err := c.ReadMessage() if err != nil { log.Println("read:", err) break } [...] app, err := models.DB.SearchAppStore(ctx, stars, updatedWithin, 0) myJson, err := json.Marshal(app) err = c.WriteMessage(mt, myJson) if err != nil { log.Println("write:", err) break } </code></pre> <p>Then I use javascript to update the HTML data this way:</p> <pre><code>ws.onmessage = function(evt) { var d = JSON.parse(evt.data); var app; for (app = 0; app < 3; app++) { document.getElementById("app-icon-" + app).src = d[app].ThumbnailURL; document.getElementById("app-title-" + app).innerHTML = d[app].Title; document.getElementById("app-compatibility-" + app).innerHTML = d[app].Compatibility; } }; </code></pre> <p>And then I have manually typed the HTML this way:</p> <pre><code><div class="app-section"> <div class="icon"> <img src="" id="app-icon-0"> </div> <div class="details"> <h2 id="app-title-0"></h2> <h5 id="app-compatibility-0"></h5> </div> </div> </code></pre> <p>You can see the 0 in the HTML 'id's, and I should note that it's much longer but I tried to only take the relevant parts..</p> <p>I would of course like not to type HTML manually since it will make it difficult(/impossible) to deal with different lenghts (like maybe sometimes I want to display a hundred apps, other times maybe there only are 3 available, etc..)</p> <p>I was thinking this might be able to be done using golang's HTML {{range}} function, but I can't figure out how to integrate it with json data from websockets..</p> <p>Another solution that should be managable is to just write out all the HTML inside the JS for loop at <code>ws.onmessage</code>, but I think it would be better if I learned how to do it using the golang template package.. Especially because it's really long and there are many classes/id's..</p> <p>The way I see it, I need to get the length of the JSON (<code>Object.keys(d).length;</code>), then somehow I need to pass this length inside {{range}} and then can use {{index}} to interate through the JSON object..</p> <p>..but I haven't been able to figure out how to do it, maybe it's not even possible.. I would greatly appreciate any help with how this can be done..</p> </div>
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页