From ea103661a9319378bfcf4a847469c5c204e1fd67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E5=AE=97=E8=BE=89?= <1050527083@qq.com> Date: Sat, 16 Nov 2024 02:30:10 +0800 Subject: [PATCH] Fix issue #4094:By using structure encapsulation parameters to achieve the purpose of user-defined JSON rendering, while not changing the functions implemented by the original code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 朱宗辉 <1050527083@qq.com> --- context.go | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/context.go b/context.go index d978a55ec3..70ac8005aa 100644 --- a/context.go +++ b/context.go @@ -52,6 +52,26 @@ const ContextRequestKey ContextKeyType = 0 // abortIndex represents a typical value used in abort functions. const abortIndex int8 = math.MaxInt8 >> 1 +// defaultJsonRenderName, default JSON render name +const defaultJsonRenderName string = "render.JSON" + +// jsonRenderRegistry, storing JSON render types and their corresponding creation factory functions +var jsonRenderRegistry = make(map[string]func(data any) render.Render) + +// RegisterJsonRender allows users to register JSON render factory functions +func (c *Context) RegisterJsonRender(name string, jsonRender func(data any) render.Render) { + jsonRenderRegistry[name] = jsonRender +} + +// createInstance, Create a JSON render instance through a factory function +func createInstance(name string, data any) render.Render { + jsonRender, exists := jsonRenderRegistry[name] + if !exists { + return jsonRenderRegistry[defaultJsonRenderName](data) + } + return jsonRender(data) +} + // Context is the most important part of gin. It allows us to pass variables between middleware, // manage the flow, validate the JSON of a request and render a JSON response for example. type Context struct { @@ -90,6 +110,15 @@ type Context struct { // sameSite allows a server to define a cookie attribute making it impossible for // the browser to send this cookie along with cross-site requests. sameSite http.SameSite + + // jsonRenderName the name of the JSON render currently used. The default value is render.JSON + // this is used to get the JSON render type when executing the c.JSON function. + jsonRenderName string +} + +// SetJSONRender set the name of the current JSON render +func (c *Context) SetJSONRender(jsonRenderName string) { + c.jsonRenderName = jsonRenderName } /************************************/ @@ -109,6 +138,9 @@ func (c *Context) reset() { c.queryCache = nil c.formCache = nil c.sameSite = 0 + // registering a default JSON renderer + c.jsonRenderName = defaultJsonRenderName + c.RegisterJsonRender(defaultJsonRenderName, render.NewJSON) *c.params = (*c.params)[:0] *c.skippedNodes = (*c.skippedNodes)[:0] } @@ -1095,7 +1127,7 @@ func (c *Context) JSONP(code int, obj any) { // JSON serializes the given struct as JSON into the response body. // It also sets the Content-Type as "application/json". func (c *Context) JSON(code int, obj any) { - c.Render(code, render.JSON{Data: obj}) + c.Render(code, createInstance(c.jsonRenderName, obj)) } // AsciiJSON serializes the given struct as JSON into the response body with unicode to ASCII string.