Home Execute template without a stuct of known format
Reply: 2

Execute template without a stuct of known format

Matt
1#
Matt Published in 2018-01-11 22:40:12Z

I have an app that is quite generic in nature.

Clients talk to it by sending json encoded messages that could contain any number of fields whose names the app does not care to know.

The app loads a configuration file and contains some template fields.

For example:

template = "Value read from json: {{.FilePath}}"

and

json from client = { "FilePath": "/tmp/filename.abc", "OtherField1":"value1" }

etc.

When using the normal golang template, a structure first needs to be defined for the json to be unmarshalled to. And then the template created and executed with values coming from the structure.

That's a problem, I don't want to have to hard code a structure together that ccontains the FilePath as a string an any other fields that a user might decide is useful. It makes it not generic.

How do I get around this? or is there perhaps another way to combining json and templates without using golang templates?

Cerise Limón
2#
Cerise Limón Reply to 2018-01-12 01:58:35Z

Unmarshal the JSON to an interface{} value and pass that value to the template Execute method. The template in the question works as is with the JSON in the question.

t := template.Must(template.New("").Parse(tmpl))
var v interface{}
if err := json.Unmarshal(jsonFromClient, &v); err != nil {
    // handle error
}
if err := t.Execute(output, v); err != nil {
    // handle error
}

Run the code on the Playground.

Sebastián Rodriguez
3#
Sebastián Rodriguez Reply to 2018-01-12 14:25:04Z

May be you can unmarshall the json into a map, and then access the data in this way: {{ index "FilePath" MyMapVar }}

I think that the index function work in the same way as with the slices.


Regards.


Edit:

Here is an example of what i said:

package main

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

func main() {
    jsonData := make(map[string]interface{})

    body := []byte(`{
            "userId": 1,
            "id": 1,
            "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
            "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
        }`)

    json.Unmarshal(body, &jsonData)

    mTemplate := `<p>UserID: {{ index . "userId" }}</p>
        <p>ID: {{ index . "id" }}</p>
        <p>Title: {{ index . "title" }}</p>
        <p>Body: {{ index . "body" }}</p>`

    http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        templ := template.New("CompiledTemplate")
        templ = template.Must(templ.Parse(mTemplate))

        templ.Execute(w, jsonData)
    })

    // Iniciamos el servidor, y retornamos el presunto error que pueda dar.
    fmt.Printf("\nEscuchando en el puerto %d\n", 9090)
    http.ListenAndServe(":"+fmt.Sprint(9090), nil)
}

It is pretty similar to the solution that Cerise Limón gave.

Also i was wrong in my first answer, the way to access an slice/map position in the template is not like this: {{ index "FilePath" MyMapVar }}, is like this: {{ index MyMapVar "FilePath" }}

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.300169 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO