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 interface{}
20
}
21

22
// IndentedJSON contains the given interface object.
23
type IndentedJSON struct {
24
	Data interface{}
25
}
26

27
// SecureJSON contains the given interface object and its prefix.
28
type SecureJSON struct {
29
	Prefix string
30
	Data   interface{}
31
}
32

33
// JsonpJSON contains the given interface object its callback.
34
type JsonpJSON struct {
35
	Callback string
36
	Data     interface{}
37
}
38

39
// AsciiJSON contains the given interface object.
40
type AsciiJSON struct {
41
	Data interface{}
42
}
43

44
// PureJSON contains the given interface object.
45
type PureJSON struct {
46
	Data interface{}
47
}
48

49
var jsonContentType = []string{"application/json; charset=utf-8"}
50
var jsonpContentType = []string{"application/javascript; charset=utf-8"}
51
var jsonAsciiContentType = []string{"application/json"}
52

53
// Render (JSON) writes data with custom ContentType.
54
func (r JSON) Render(w http.ResponseWriter) (err error) {
55 6
	if err = WriteJSON(w, r.Data); err != nil {
56 6
		panic(err)
57
	}
58 6
	return
59
}
60

61
// WriteContentType (JSON) writes JSON ContentType.
62
func (r JSON) WriteContentType(w http.ResponseWriter) {
63 6
	writeContentType(w, jsonContentType)
64
}
65

66
// WriteJSON marshals the given interface object and writes it with custom ContentType.
67
func WriteJSON(w http.ResponseWriter, obj interface{}) error {
68 6
	writeContentType(w, jsonContentType)
69 6
	jsonBytes, err := json.Marshal(obj)
70 6
	if err != nil {
71 6
		return err
72
	}
73 6
	_, err = w.Write(jsonBytes)
74 6
	return err
75
}
76

77
// Render (IndentedJSON) marshals the given interface object and writes it with custom ContentType.
78
func (r IndentedJSON) Render(w http.ResponseWriter) error {
79 6
	r.WriteContentType(w)
80 6
	jsonBytes, err := json.MarshalIndent(r.Data, "", "    ")
81 6
	if err != nil {
82 6
		return err
83
	}
84 6
	_, err = w.Write(jsonBytes)
85 6
	return err
86
}
87

88
// WriteContentType (IndentedJSON) writes JSON ContentType.
89
func (r IndentedJSON) WriteContentType(w http.ResponseWriter) {
90 6
	writeContentType(w, jsonContentType)
91
}
92

93
// Render (SecureJSON) marshals the given interface object and writes it with custom ContentType.
94
func (r SecureJSON) Render(w http.ResponseWriter) error {
95 6
	r.WriteContentType(w)
96 6
	jsonBytes, err := json.Marshal(r.Data)
97 6
	if err != nil {
98 6
		return err
99
	}
100
	// if the jsonBytes is array values
101 6
	if bytes.HasPrefix(jsonBytes, bytesconv.StringToBytes("[")) && bytes.HasSuffix(jsonBytes,
102 6
		bytesconv.StringToBytes("]")) {
103 6
		_, err = w.Write(bytesconv.StringToBytes(r.Prefix))
104 6
		if err != nil {
105 0
			return err
106
		}
107
	}
108 6
	_, err = w.Write(jsonBytes)
109 6
	return err
110
}
111

112
// WriteContentType (SecureJSON) writes JSON ContentType.
113
func (r SecureJSON) WriteContentType(w http.ResponseWriter) {
114 6
	writeContentType(w, jsonContentType)
115
}
116

117
// Render (JsonpJSON) marshals the given interface object and writes it and its callback with custom ContentType.
118
func (r JsonpJSON) Render(w http.ResponseWriter) (err error) {
119 6
	r.WriteContentType(w)
120 6
	ret, err := json.Marshal(r.Data)
121 6
	if err != nil {
122 6
		return err
123
	}
124

125 6
	if r.Callback == "" {
126 6
		_, err = w.Write(ret)
127 6
		return err
128
	}
129

130 6
	callback := template.JSEscapeString(r.Callback)
131 6
	_, err = w.Write(bytesconv.StringToBytes(callback))
132 6
	if err != nil {
133 0
		return err
134
	}
135 6
	_, err = w.Write(bytesconv.StringToBytes("("))
136 6
	if err != nil {
137 0
		return err
138
	}
139 6
	_, err = w.Write(ret)
140 6
	if err != nil {
141 0
		return err
142
	}
143 6
	_, err = w.Write(bytesconv.StringToBytes(");"))
144 6
	if err != nil {
145 0
		return err
146
	}
147

148 6
	return nil
149
}
150

151
// WriteContentType (JsonpJSON) writes Javascript ContentType.
152
func (r JsonpJSON) WriteContentType(w http.ResponseWriter) {
153 6
	writeContentType(w, jsonpContentType)
154
}
155

156
// Render (AsciiJSON) marshals the given interface object and writes it with custom ContentType.
157
func (r AsciiJSON) Render(w http.ResponseWriter) (err error) {
158 6
	r.WriteContentType(w)
159 6
	ret, err := json.Marshal(r.Data)
160 6
	if err != nil {
161 6
		return err
162
	}
163

164 6
	var buffer bytes.Buffer
165
	for _, r := range bytesconv.BytesToString(ret) {
166 6
		cvt := string(r)
167 6
		if r >= 128 {
168 6
			cvt = fmt.Sprintf("\\u%04x", int64(r))
169
		}
170 6
		buffer.WriteString(cvt)
171
	}
172

173 6
	_, err = w.Write(buffer.Bytes())
174 6
	return err
175
}
176

177
// WriteContentType (AsciiJSON) writes JSON ContentType.
178
func (r AsciiJSON) WriteContentType(w http.ResponseWriter) {
179 6
	writeContentType(w, jsonAsciiContentType)
180
}
181

182
// Render (PureJSON) writes custom ContentType and encodes the given interface object.
183
func (r PureJSON) Render(w http.ResponseWriter) error {
184 6
	r.WriteContentType(w)
185 6
	encoder := json.NewEncoder(w)
186 6
	encoder.SetEscapeHTML(false)
187 6
	return encoder.Encode(r.Data)
188
}
189

190
// WriteContentType (PureJSON) writes custom ContentType.
191
func (r PureJSON) WriteContentType(w http.ResponseWriter) {
192 6
	writeContentType(w, jsonContentType)
193
}

Read our documentation on viewing source code .

Loading