Skip to content

Commit

Permalink
Add PureJSON renderer (#694)
Browse files Browse the repository at this point in the history
Closes #693
  • Loading branch information
ffigiel authored and appleboy committed Aug 20, 2018
1 parent b7bb9ba commit c6110f9
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 4 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,34 @@ func main() {
}
```

#### PureJSON

Normally, JSON replaces special HTML characters with their unicode entities, e.g. `<` becomes `\u003c`. If you want to encode such characters literally, you can use PureJSON instead.
This feature is unavailable in Go 1.6 and lower.

```go
func main() {
r := gin.Default()

// Serves unicode entities
r.GET("/json", func(c *gin.Context) {
c.JSON(200, gin.H{
"html": "<b>Hello, world!</b>",
})
})

// Serves literal characters
r.GET("/purejson", func(c *gin.Context) {
c.PureJSON(200, gin.H{
"html": "<b>Hello, world!</b>",
})
})

// listen and serve on 0.0.0.0:8080
r.Run(":8080)
}
```
### Serving static files
```go
Expand Down
17 changes: 17 additions & 0 deletions context_17.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2018 Gin Core Team. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

// +build go1.7

package gin

import (
"github.com/gin-gonic/gin/render"
)

// PureJSON serializes the given struct as JSON into the response body.
// PureJSON, unlike JSON, does not replace special html characters with their unicode entities.
func (c *Context) PureJSON(code int, obj interface{}) {
c.Render(code, render.PureJSON{Data: obj})
}
27 changes: 27 additions & 0 deletions context_17_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2018 Gin Core Team. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

// +build go1.7

package gin

import (
"net/http"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/assert"
)

// Tests that the response is serialized as JSON
// and Content-Type is set to application/json
// and special HTML characters are preserved
func TestContextRenderPureJSON(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.PureJSON(http.StatusCreated, H{"foo": "bar", "html": "<b>"})
assert.Equal(t, http.StatusCreated, w.Code)
assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"<b>\"}\n", w.Body.String())
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type"))
}
5 changes: 3 additions & 2 deletions context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -619,14 +619,15 @@ func TestContextRenderPanicIfErr(t *testing.T) {

// Tests that the response is serialized as JSON
// and Content-Type is set to application/json
// and special HTML characters are escaped
func TestContextRenderJSON(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)

c.JSON(http.StatusCreated, H{"foo": "bar"})
c.JSON(http.StatusCreated, H{"foo": "bar", "html": "<b>"})

assert.Equal(t, http.StatusCreated, w.Code)
assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String())
assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}", w.Body.String())
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type"))
}

Expand Down
1 change: 1 addition & 0 deletions json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ var (
Marshal = json.Marshal
MarshalIndent = json.MarshalIndent
NewDecoder = json.NewDecoder
NewEncoder = json.NewEncoder
)
28 changes: 28 additions & 0 deletions render/json_17.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2018 Gin Core Team. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

// +build go1.7

package render

import (
"net/http"

"github.com/gin-gonic/gin/json"
)

type PureJSON struct {
Data interface{}
}

func (r PureJSON) Render(w http.ResponseWriter) error {
r.WriteContentType(w)
encoder := json.NewEncoder(w)
encoder.SetEscapeHTML(false)
return encoder.Encode(r.Data)
}

func (r PureJSON) WriteContentType(w http.ResponseWriter) {
writeContentType(w, jsonContentType)
}
26 changes: 26 additions & 0 deletions render/render_17_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2018 Gin Core Team. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

// +build go1.7

package render

import (
"net/http/httptest"
"testing"

"github.com/stretchr/testify/assert"
)

func TestRenderPureJSON(t *testing.T) {
w := httptest.NewRecorder()
data := map[string]interface{}{
"foo": "bar",
"html": "<b>",
}
err := (PureJSON{data}).Render(w)
assert.NoError(t, err)
assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"<b>\"}\n", w.Body.String())
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
}
5 changes: 3 additions & 2 deletions render/render_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ func TestRenderMsgPack(t *testing.T) {
func TestRenderJSON(t *testing.T) {
w := httptest.NewRecorder()
data := map[string]interface{}{
"foo": "bar",
"foo": "bar",
"html": "<b>",
}

(JSON{data}).WriteContentType(w)
Expand All @@ -61,7 +62,7 @@ func TestRenderJSON(t *testing.T) {
err := (JSON{data}).Render(w)

assert.NoError(t, err)
assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String())
assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}", w.Body.String())
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
}

Expand Down

0 comments on commit c6110f9

Please sign in to comment.