mirror of
https://github.com/gin-gonic/gin.git
synced 2026-06-04 17:58:14 +08:00
docs: add json-iterator example
This commit is contained in:
parent
b2b489dbf4
commit
e0109c70d9
62
PR_DESCRIPTION.md
Normal file
62
PR_DESCRIPTION.md
Normal file
@ -0,0 +1,62 @@
|
||||
### What problem does this PR solve?
|
||||
|
||||
Issue Number: Close #2810
|
||||
|
||||
Problem Summary:
|
||||
Users have requested an example of how to integrate `json-iterator` with Gin at runtime (without using build tags). While there is documentation, a runnable example project is helpful for understanding the integration points, specifically implementing the `json.Core` interface and replacing `json.API`.
|
||||
|
||||
### What is changed and how does it work?
|
||||
|
||||
- Added a new example under `examples/json-iterator`.
|
||||
- Implemented `customJsonApi` which wraps `jsoniter.Config` and implements `json.Core`.
|
||||
- Demonstrates how to replace the default `json.API` with the custom implementation.
|
||||
- Added a unit test to verify the integration works as expected.
|
||||
- Added a README for the example explaining how to run and test it.
|
||||
|
||||
### Check List
|
||||
|
||||
Tests
|
||||
|
||||
- [x] Unit test
|
||||
- Added `examples/json-iterator/json_iterator_test.go`
|
||||
- [ ] Integration test
|
||||
- [x] Manual test
|
||||
- Verified with `curl` locally.
|
||||
- [ ] No code
|
||||
|
||||
Code changes
|
||||
|
||||
- [ ] Has the configuration change
|
||||
- [ ] Has HTTP API interfaces changed
|
||||
- [ ] Has persistent data change
|
||||
|
||||
Side effects
|
||||
|
||||
- [ ] Possible performance regression
|
||||
- [ ] Increased code complexity
|
||||
- [ ] Breaking backward compatibility
|
||||
|
||||
Related changes
|
||||
|
||||
- [ ] PR to update [`pingcap/docs`](https://github.com/pingcap/docs)/[`pingcap/docs-cn`](https://github.com/pingcap/docs-cn):
|
||||
- [ ] PR to update [`pingcap/tiup`](https://github.com/pingcap/tiup):
|
||||
- [ ] Need to cherry-pick to the release branch
|
||||
|
||||
### How to Test
|
||||
|
||||
1. Navigate to the example directory:
|
||||
```bash
|
||||
cd examples/json-iterator
|
||||
```
|
||||
2. Run the tests:
|
||||
```bash
|
||||
go test -v
|
||||
```
|
||||
3. Run the example:
|
||||
```bash
|
||||
go run main.go
|
||||
```
|
||||
4. Make a request:
|
||||
```bash
|
||||
curl http://localhost:8080/ping
|
||||
```
|
||||
26
examples/json-iterator/README.md
Normal file
26
examples/json-iterator/README.md
Normal file
@ -0,0 +1,26 @@
|
||||
# JSON Iterator Example
|
||||
|
||||
This example demonstrates how to integrate [json-iterator/go](https://github.com/json-iterator/go) with Gin to replace the default encoding/json for better performance.
|
||||
|
||||
## How it works
|
||||
|
||||
Gin supports custom JSON serialization and deserialization logic via the `json.API` variable. By implementing the `json.Core` interface (which includes `Marshal`, `Unmarshal`, `NewEncoder`, `NewDecoder` etc.), we can swap out the underlying JSON engine.
|
||||
|
||||
## Usage
|
||||
|
||||
1. Define your custom configuration using `jsoniter.Config`.
|
||||
2. Implement the `json.Core` interface wrappers.
|
||||
3. Assign your custom implementation to `json.API` before creating the Gin engine.
|
||||
|
||||
## Run the example
|
||||
|
||||
```bash
|
||||
go run main.go
|
||||
```
|
||||
|
||||
Test it:
|
||||
|
||||
```bash
|
||||
curl http://localhost:8080/ping
|
||||
# Output: {"message":"pong"}
|
||||
```
|
||||
45
examples/json-iterator/json_iterator_test.go
Normal file
45
examples/json-iterator/json_iterator_test.go
Normal file
@ -0,0 +1,45 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
ginjson "github.com/gin-gonic/gin/codec/json"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestJsonIterator(t *testing.T) {
|
||||
// Restore default json api after test
|
||||
originalAPI := ginjson.API
|
||||
defer func() {
|
||||
ginjson.API = originalAPI
|
||||
}()
|
||||
|
||||
// Use custom json api
|
||||
ginjson.API = customJsonApi{}
|
||||
|
||||
gin.SetMode(gin.TestMode)
|
||||
r := gin.New()
|
||||
r.GET("/test", func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"hello": "world",
|
||||
"foo": "bar",
|
||||
})
|
||||
})
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest("GET", "/test", nil)
|
||||
r.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
|
||||
// Verify JSON response
|
||||
var response map[string]string
|
||||
err := json.Unmarshal(w.Body.Bytes(), &response)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "world", response["hello"])
|
||||
assert.Equal(t, "bar", response["foo"])
|
||||
}
|
||||
55
examples/json-iterator/main.go
Normal file
55
examples/json-iterator/main.go
Normal file
@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/codec/json"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
)
|
||||
|
||||
var customConfig = jsoniter.Config{
|
||||
EscapeHTML: true,
|
||||
SortMapKeys: true,
|
||||
ValidateJsonRawMessage: true,
|
||||
}.Froze()
|
||||
|
||||
// customJsonApi implement api.JsonApi
|
||||
type customJsonApi struct {
|
||||
}
|
||||
|
||||
func (j customJsonApi) Marshal(v any) ([]byte, error) {
|
||||
return customConfig.Marshal(v)
|
||||
}
|
||||
|
||||
func (j customJsonApi) Unmarshal(data []byte, v any) error {
|
||||
return customConfig.Unmarshal(data, v)
|
||||
}
|
||||
|
||||
func (j customJsonApi) MarshalIndent(v any, prefix, indent string) ([]byte, error) {
|
||||
return customConfig.MarshalIndent(v, prefix, indent)
|
||||
}
|
||||
|
||||
func (j customJsonApi) NewEncoder(writer io.Writer) json.Encoder {
|
||||
return customConfig.NewEncoder(writer)
|
||||
}
|
||||
|
||||
func (j customJsonApi) NewDecoder(reader io.Reader) json.Decoder {
|
||||
return customConfig.NewDecoder(reader)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Replace the default json api with json-iterator
|
||||
json.API = customJsonApi{}
|
||||
|
||||
r := gin.Default()
|
||||
|
||||
r.GET("/ping", func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "pong",
|
||||
})
|
||||
})
|
||||
|
||||
r.Run(":8080")
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user