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