diff --git a/context.go b/context.go index 5b67dcc0..bb35f0c2 100644 --- a/context.go +++ b/context.go @@ -679,6 +679,12 @@ func (c *Context) JSON(code int, obj interface{}) { c.Render(code, render.JSON{Data: obj}) } +// 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}) +} + // XML serializes the given struct as XML into the response body. // It also sets the Content-Type as "application/xml". func (c *Context) XML(code int, obj interface{}) { diff --git a/context_test.go b/context_test.go index 8cd05f6c..67f37dae 100644 --- a/context_test.go +++ b/context_test.go @@ -570,14 +570,29 @@ 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(201, H{"foo": "bar"}) + c.JSON(http.StatusCreated, H{"foo": "bar", "html": ""}) - assert.Equal(t, 201, w.Code) - assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String()) + assert.Equal(t, http.StatusCreated, w.Code) + assert.Equal( + t, + "{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}\n", + w.Body.String()) + assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type")) +} + +// 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) { + c, w, _ := CreateTestContext() + c.PureJSON(201, H{"foo": "bar", "html": ""}) + assert.Equal(t, w.Code, 201) + assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"\"}\n", w.Body.String()) assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type")) } diff --git a/render/json.go b/render/json.go index eb2548e2..8c659378 100644 --- a/render/json.go +++ b/render/json.go @@ -15,6 +15,11 @@ type JSON struct { Data interface{} } +type PureJSON struct { + Data interface{} +} + + type IndentedJSON struct { Data interface{} } @@ -49,6 +54,13 @@ func WriteJSON(w http.ResponseWriter, obj interface{}) error { return nil } +func (r PureJSON) Render(w http.ResponseWriter) error { + writeContentType(w, jsonContentType) + encoder := json.NewEncoder(w) + encoder.SetEscapeHTML(false) + return encoder.Encode(r.Data) +} + func (r IndentedJSON) Render(w http.ResponseWriter) error { r.WriteContentType(w) jsonBytes, err := json.MarshalIndent(r.Data, "", " ") diff --git a/render/render_test.go b/render/render_test.go index e4df5b6d..319a42b0 100644 --- a/render/render_test.go +++ b/render/render_test.go @@ -43,12 +43,29 @@ func TestRenderJSON(t *testing.T) { w := httptest.NewRecorder() data := map[string]interface{}{ "foo": "bar", + "html": "", } err := (JSON{data}).Render(w) assert.NoError(t, err) assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String()) + assert.Equal( + t, + w.Body.String(), + "{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}\n") + assert.Equal(t, w.Header().Get("Content-Type"), "application/json; charset=utf-8") +} + +func TestRenderPureJSON(t *testing.T) { + w := httptest.NewRecorder() + data := map[string]interface{}{ + "foo": "bar", + "html": "", + } + err := (PureJSON{data}).Render(w) + assert.NoError(t, err) + assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"\"}\n", w.Body.String()) assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type")) }