Last active
April 19, 2016 15:09
-
-
Save saml/e42a12812dc94168f4ed75da63db2916 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "bytes" | |
| "encoding/json" | |
| "fmt" | |
| "html/template" | |
| ) | |
| type WebPage struct { | |
| Title string `json:"title"` | |
| Components []Component `json:"components"` | |
| } | |
| type Component interface { | |
| HTML() template.HTML | |
| Type() string | |
| } | |
| type webPage struct { | |
| Title string `json:"title"` | |
| Components []*component `json:"components"` | |
| } | |
| type component struct { | |
| Type string `json:"_type"` | |
| Args json.RawMessage `json:"_args"` | |
| } | |
| func (p *WebPage) UnmarshalJSON(d []byte) error { | |
| var w webPage | |
| err := json.Unmarshal(d, &w) | |
| if err != nil { | |
| return err | |
| } | |
| p.Title = w.Title | |
| p.Components = make([]Component, 0) | |
| var component interface{} | |
| for _, c := range w.Components { | |
| switch c.Type { | |
| case "Image": | |
| component = new(Image) | |
| case "Author": | |
| component = new(Author) | |
| case "Paragraph": | |
| component = new(Paragraph) | |
| } | |
| err = json.Unmarshal(c.Args, component) | |
| if err != nil { | |
| panic(err) | |
| } | |
| p.Components = append(p.Components, component.(Component)) | |
| } | |
| return nil | |
| } | |
| func (p *WebPage) MarshalJSON() ([]byte, error) { | |
| var w webPage | |
| w.Title = p.Title | |
| w.Components = make([]*component, 0, len(p.Components)) | |
| for _, c := range p.Components { | |
| b, err := json.Marshal(c) | |
| if err != nil { | |
| panic(err) | |
| } | |
| w.Components = append(w.Components, &component{ | |
| Type: c.Type(), | |
| Args: b, | |
| }) | |
| } | |
| b, err := json.Marshal(w) | |
| if err != nil { | |
| panic(err) | |
| } | |
| return b, nil | |
| } | |
| type Image struct { | |
| URL string `json:"url"` | |
| Width int `json:"width"` | |
| } | |
| func (i *Image) Type() string { | |
| return "Image" | |
| } | |
| func (i *Image) HTML() template.HTML { | |
| return template.HTML(fmt.Sprintf(`<img src="%s" width="%d">`, i.URL, i.Width)) | |
| } | |
| type Author struct { | |
| URL string `json:"url"` | |
| Name string `json:"name"` | |
| } | |
| func (a *Author) Type() string { | |
| return "Author" | |
| } | |
| func (a *Author) HTML() template.HTML { | |
| return template.HTML(fmt.Sprintf(`<a rel="author" href="%s">%s</a>`, a.URL, a.Name)) | |
| } | |
| type Paragraph struct { | |
| Text string `json:"text"` | |
| } | |
| func (p *Paragraph) Type() string { | |
| return "Paragraph" | |
| } | |
| func (p *Paragraph) HTML() template.HTML { | |
| return template.HTML(fmt.Sprintf(`<p>%s</p>`, p.Text)) | |
| } | |
| func JSON(x interface{}) string { | |
| b, err := json.Marshal(x) | |
| if err != nil { | |
| panic(err) | |
| } | |
| return string(b) | |
| } | |
| func (p *WebPage) HTML() string { | |
| tmpl := `<!doctype html> | |
| <meta charset="utf-8"> | |
| <title>{{.Title}}</title> | |
| {{range .Components}}{{.HTML}}{{end}} | |
| ` | |
| var b bytes.Buffer | |
| t, _ := template.New("web").Parse(tmpl) | |
| t.Execute(&b, p) | |
| return b.String() | |
| } | |
| func (p *WebPage) Type() string { | |
| return "WebPage" | |
| } | |
| func main() { | |
| payload := []byte(` | |
| {"components":[ | |
| {"_type": "Image", "_args": {"url": "/a.jpg", "width": 100}}, | |
| {"_type": "Author", "_args": {"name": "Foo Bar", "url": "/authors/1/"}}, | |
| {"_type": "Paragraph", "_args": {"text": "foo bar yolo"}}], | |
| "componentsLength": 3, | |
| "title": "a web page. react.js wow" | |
| } | |
| `) | |
| var webPage WebPage | |
| err := json.Unmarshal(payload, &webPage) | |
| if err != nil { | |
| panic(err) | |
| } | |
| fmt.Println(JSON(&webPage)) | |
| fmt.Println(webPage.HTML()) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment