// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. package render import ( "bytes" "fmt" "html/template" "net/http" "github.com/gin-gonic/gin/json" ) type JSON struct { Data interface{} } type IndentedJSON struct { Data interface{} } type SecureJSON struct { Prefix string Data interface{} } type JsonpJSON struct { Callback string Data interface{} } type AsciiJSON struct { Data interface{} } type SecureJSONPrefix string var jsonContentType = []string{"application/json; charset=utf-8"} var jsonpContentType = []string{"application/javascript; charset=utf-8"} var jsonAsciiContentType = []string{"application/json"} func (r JSON) Render(w http.ResponseWriter) (err error) { if err = WriteJSON(w, r.Data); err != nil { panic(err) } return } func (r JSON) WriteContentType(w http.ResponseWriter) { writeContentType(w, jsonContentType) } func WriteJSON(w http.ResponseWriter, obj interface{}) error { writeContentType(w, jsonContentType) jsonBytes, err := json.Marshal(obj) if err != nil { return err } w.Write(jsonBytes) return nil } func (r IndentedJSON) Render(w http.ResponseWriter) error { r.WriteContentType(w) jsonBytes, err := json.MarshalIndent(r.Data, "", " ") if err != nil { return err } w.Write(jsonBytes) return nil } func (r IndentedJSON) WriteContentType(w http.ResponseWriter) { writeContentType(w, jsonContentType) } func (r SecureJSON) Render(w http.ResponseWriter) error { r.WriteContentType(w) jsonBytes, err := json.Marshal(r.Data) if err != nil { return err } // if the jsonBytes is array values if bytes.HasPrefix(jsonBytes, []byte("[")) && bytes.HasSuffix(jsonBytes, []byte("]")) { w.Write([]byte(r.Prefix)) } w.Write(jsonBytes) return nil } func (r SecureJSON) WriteContentType(w http.ResponseWriter) { writeContentType(w, jsonContentType) } func (r JsonpJSON) Render(w http.ResponseWriter) (err error) { r.WriteContentType(w) ret, err := json.Marshal(r.Data) if err != nil { return err } if r.Callback == "" { w.Write(ret) return nil } callback := template.JSEscapeString(r.Callback) w.Write([]byte(callback)) w.Write([]byte("(")) w.Write(ret) w.Write([]byte(")")) return nil } func (r JsonpJSON) WriteContentType(w http.ResponseWriter) { writeContentType(w, jsonpContentType) } func (r AsciiJSON) Render(w http.ResponseWriter) (err error) { r.WriteContentType(w) ret, err := json.Marshal(r.Data) if err != nil { return err } var buffer bytes.Buffer for _, r := range string(ret) { cvt := "" if r < 128 { cvt = string(r) } else { cvt = fmt.Sprintf("\\u%04x", int64(r)) } buffer.WriteString(cvt) } w.Write(buffer.Bytes()) return nil } func (r AsciiJSON) WriteContentType(w http.ResponseWriter) { writeContentType(w, jsonAsciiContentType) }