1// Copyright 2014 Manu Martinez-Almeida. All rights reserved. 2// Use of this source code is governed by a MIT style 3// license that can be found in the LICENSE file. 4 5package render 6 7import ( 8 "bytes" 9 "fmt" 10 "html/template" 11 "net/http" 12 13 "github.com/gin-gonic/gin/internal/bytesconv" 14 "github.com/gin-gonic/gin/internal/json" 15) 16 17// JSON contains the given interface object. 18type JSON struct { 19 Data interface{} 20} 21 22// IndentedJSON contains the given interface object. 23type IndentedJSON struct { 24 Data interface{} 25} 26 27// SecureJSON contains the given interface object and its prefix. 28type SecureJSON struct { 29 Prefix string 30 Data interface{} 31} 32 33// JsonpJSON contains the given interface object its callback. 34type JsonpJSON struct { 35 Callback string 36 Data interface{} 37} 38 39// AsciiJSON contains the given interface object. 40type AsciiJSON struct { 41 Data interface{} 42} 43 44// SecureJSONPrefix is a string which represents SecureJSON prefix. 45type SecureJSONPrefix string 46 47// PureJSON contains the given interface object. 48type PureJSON struct { 49 Data interface{} 50} 51 52var jsonContentType = []string{"application/json; charset=utf-8"} 53var jsonpContentType = []string{"application/javascript; charset=utf-8"} 54var jsonAsciiContentType = []string{"application/json"} 55 56// Render (JSON) writes data with custom ContentType. 57func (r JSON) Render(w http.ResponseWriter) (err error) { 58 if err = WriteJSON(w, r.Data); err != nil { 59 panic(err) 60 } 61 return 62} 63 64// WriteContentType (JSON) writes JSON ContentType. 65func (r JSON) WriteContentType(w http.ResponseWriter) { 66 writeContentType(w, jsonContentType) 67} 68 69// WriteJSON marshals the given interface object and writes it with custom ContentType. 70func WriteJSON(w http.ResponseWriter, obj interface{}) error { 71 writeContentType(w, jsonContentType) 72 jsonBytes, err := json.Marshal(obj) 73 if err != nil { 74 return err 75 } 76 _, err = w.Write(jsonBytes) 77 return err 78} 79 80// Render (IndentedJSON) marshals the given interface object and writes it with custom ContentType. 81func (r IndentedJSON) Render(w http.ResponseWriter) error { 82 r.WriteContentType(w) 83 jsonBytes, err := json.MarshalIndent(r.Data, "", " ") 84 if err != nil { 85 return err 86 } 87 _, err = w.Write(jsonBytes) 88 return err 89} 90 91// WriteContentType (IndentedJSON) writes JSON ContentType. 92func (r IndentedJSON) WriteContentType(w http.ResponseWriter) { 93 writeContentType(w, jsonContentType) 94} 95 96// Render (SecureJSON) marshals the given interface object and writes it with custom ContentType. 97func (r SecureJSON) Render(w http.ResponseWriter) error { 98 r.WriteContentType(w) 99 jsonBytes, err := json.Marshal(r.Data) 100 if err != nil { 101 return err 102 } 103 // if the jsonBytes is array values 104 if bytes.HasPrefix(jsonBytes, bytesconv.StringToBytes("[")) && bytes.HasSuffix(jsonBytes, 105 bytesconv.StringToBytes("]")) { 106 _, err = w.Write(bytesconv.StringToBytes(r.Prefix)) 107 if err != nil { 108 return err 109 } 110 } 111 _, err = w.Write(jsonBytes) 112 return err 113} 114 115// WriteContentType (SecureJSON) writes JSON ContentType. 116func (r SecureJSON) WriteContentType(w http.ResponseWriter) { 117 writeContentType(w, jsonContentType) 118} 119 120// Render (JsonpJSON) marshals the given interface object and writes it and its callback with custom ContentType. 121func (r JsonpJSON) Render(w http.ResponseWriter) (err error) { 122 r.WriteContentType(w) 123 ret, err := json.Marshal(r.Data) 124 if err != nil { 125 return err 126 } 127 128 if r.Callback == "" { 129 _, err = w.Write(ret) 130 return err 131 } 132 133 callback := template.JSEscapeString(r.Callback) 134 _, err = w.Write(bytesconv.StringToBytes(callback)) 135 if err != nil { 136 return err 137 } 138 _, err = w.Write(bytesconv.StringToBytes("(")) 139 if err != nil { 140 return err 141 } 142 _, err = w.Write(ret) 143 if err != nil { 144 return err 145 } 146 _, err = w.Write(bytesconv.StringToBytes(");")) 147 if err != nil { 148 return err 149 } 150 151 return nil 152} 153 154// WriteContentType (JsonpJSON) writes Javascript ContentType. 155func (r JsonpJSON) WriteContentType(w http.ResponseWriter) { 156 writeContentType(w, jsonpContentType) 157} 158 159// Render (AsciiJSON) marshals the given interface object and writes it with custom ContentType. 160func (r AsciiJSON) Render(w http.ResponseWriter) (err error) { 161 r.WriteContentType(w) 162 ret, err := json.Marshal(r.Data) 163 if err != nil { 164 return err 165 } 166 167 var buffer bytes.Buffer 168 for _, r := range bytesconv.BytesToString(ret) { 169 cvt := string(r) 170 if r >= 128 { 171 cvt = fmt.Sprintf("\\u%04x", int64(r)) 172 } 173 buffer.WriteString(cvt) 174 } 175 176 _, err = w.Write(buffer.Bytes()) 177 return err 178} 179 180// WriteContentType (AsciiJSON) writes JSON ContentType. 181func (r AsciiJSON) WriteContentType(w http.ResponseWriter) { 182 writeContentType(w, jsonAsciiContentType) 183} 184 185// Render (PureJSON) writes custom ContentType and encodes the given interface object. 186func (r PureJSON) Render(w http.ResponseWriter) error { 187 r.WriteContentType(w) 188 encoder := json.NewEncoder(w) 189 encoder.SetEscapeHTML(false) 190 return encoder.Encode(r.Data) 191} 192 193// WriteContentType (PureJSON) writes custom ContentType. 194func (r PureJSON) WriteContentType(w http.ResponseWriter) { 195 writeContentType(w, jsonContentType) 196} 197