forked from mirror/gin
add json ASCII string render (#1358)
add a json render that rendering json as ASCII string
This commit is contained in:
parent
d17a12591f
commit
85221af84c
23
README.md
23
README.md
|
@ -900,6 +900,29 @@ func main() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### AsciiJSON
|
||||||
|
|
||||||
|
Using AsciiJSON to Generates ASCII-only JSON with escaped non-ASCII chracters.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
r := gin.Default()
|
||||||
|
|
||||||
|
r.GET("/someJSON", func(c *gin.Context) {
|
||||||
|
data := map[string]interface{}{
|
||||||
|
"lang": "GO语言",
|
||||||
|
"tag": "<br>",
|
||||||
|
}
|
||||||
|
|
||||||
|
// will output : {"lang":"GO\u8bed\u8a00","tag":"\u003cbr\u003e"}
|
||||||
|
c.AsciiJSON(http.StatusOK, data)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Listen and serve on 0.0.0.0:8080
|
||||||
|
r.Run(":8080")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Serving static files
|
### Serving static files
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
|
|
@ -704,6 +704,12 @@ func (c *Context) JSON(code int, obj interface{}) {
|
||||||
c.Render(code, render.JSON{Data: obj})
|
c.Render(code, render.JSON{Data: obj})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AsciiJSON serializes the given struct as JSON into the response body with unicode to ASCII string.
|
||||||
|
// It also sets the Content-Type as "application/json".
|
||||||
|
func (c *Context) AsciiJSON(code int, obj interface{}) {
|
||||||
|
c.Render(code, render.AsciiJSON{Data: obj})
|
||||||
|
}
|
||||||
|
|
||||||
// XML serializes the given struct as XML into the response body.
|
// XML serializes the given struct as XML into the response body.
|
||||||
// It also sets the Content-Type as "application/xml".
|
// It also sets the Content-Type as "application/xml".
|
||||||
func (c *Context) XML(code int, obj interface{}) {
|
func (c *Context) XML(code int, obj interface{}) {
|
||||||
|
|
|
@ -686,6 +686,17 @@ func TestContextRenderNoContentSecureJSON(t *testing.T) {
|
||||||
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestContextRenderNoContentAsciiJSON(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, _ := CreateTestContext(w)
|
||||||
|
|
||||||
|
c.AsciiJSON(http.StatusNoContent, []string{"lang", "Go语言"})
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusNoContent, w.Code)
|
||||||
|
assert.Empty(t, w.Body.String())
|
||||||
|
assert.Equal(t, "application/json", w.HeaderMap.Get("Content-Type"))
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that the response executes the templates
|
// Tests that the response executes the templates
|
||||||
// and responds with Content-Type set to text/html
|
// and responds with Content-Type set to text/html
|
||||||
func TestContextRenderHTML(t *testing.T) {
|
func TestContextRenderHTML(t *testing.T) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ package render
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -30,10 +31,15 @@ type JsonpJSON struct {
|
||||||
Data interface{}
|
Data interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AsciiJSON struct {
|
||||||
|
Data interface{}
|
||||||
|
}
|
||||||
|
|
||||||
type SecureJSONPrefix string
|
type SecureJSONPrefix string
|
||||||
|
|
||||||
var jsonContentType = []string{"application/json; charset=utf-8"}
|
var jsonContentType = []string{"application/json; charset=utf-8"}
|
||||||
var jsonpContentType = []string{"application/javascript; 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) {
|
func (r JSON) Render(w http.ResponseWriter) (err error) {
|
||||||
if err = WriteJSON(w, r.Data); err != nil {
|
if err = WriteJSON(w, r.Data); err != nil {
|
||||||
|
@ -112,3 +118,29 @@ func (r JsonpJSON) Render(w http.ResponseWriter) (err error) {
|
||||||
func (r JsonpJSON) WriteContentType(w http.ResponseWriter) {
|
func (r JsonpJSON) WriteContentType(w http.ResponseWriter) {
|
||||||
writeContentType(w, jsonpContentType)
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -167,6 +167,35 @@ func TestRenderJsonpJSONFail(t *testing.T) {
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRenderAsciiJSON(t *testing.T) {
|
||||||
|
w1 := httptest.NewRecorder()
|
||||||
|
data1 := map[string]interface{}{
|
||||||
|
"lang": "GO语言",
|
||||||
|
"tag": "<br>",
|
||||||
|
}
|
||||||
|
|
||||||
|
err := (AsciiJSON{data1}).Render(w1)
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "{\"lang\":\"GO\\u8bed\\u8a00\",\"tag\":\"\\u003cbr\\u003e\"}", w1.Body.String())
|
||||||
|
assert.Equal(t, "application/json", w1.Header().Get("Content-Type"))
|
||||||
|
|
||||||
|
w2 := httptest.NewRecorder()
|
||||||
|
data2 := float64(3.1415926)
|
||||||
|
|
||||||
|
err = (AsciiJSON{data2}).Render(w2)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "3.1415926", w2.Body.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRenderAsciiJSONFail(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
data := make(chan int)
|
||||||
|
|
||||||
|
// json: unsupported type: chan int
|
||||||
|
assert.Error(t, (AsciiJSON{data}).Render(w))
|
||||||
|
}
|
||||||
|
|
||||||
type xmlmap map[string]interface{}
|
type xmlmap map[string]interface{}
|
||||||
|
|
||||||
// Allows type H to be used with xml.Marshal
|
// Allows type H to be used with xml.Marshal
|
||||||
|
|
Loading…
Reference in New Issue