add json ASCII string render (#1358)
add a json render that rendering json as ASCII string
This commit is contained in:
		
							
								
								
									
										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
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user