Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom JSON binding or middleware ? #917

Open
philippecarle opened this issue May 19, 2017 · 1 comment
Open

Custom JSON binding or middleware ? #917

philippecarle opened this issue May 19, 2017 · 1 comment

Comments

@philippecarle
Copy link

philippecarle commented May 19, 2017

I'm looking for a way to use https://github.com/google/jsonapi as a JSON (un)serializer. To be able to have custom bindings would be great but even though I looked for way to manage this, I couldn't guess how.

My idea then was to use a middleware to achieve this.

  • set a custom "resource" value (a model) in the context by using a custom middleware
  • populate this model by unmarshaling the request body in a common/generic middleware

Here is what my I made to make it working:

In main.go

	// subscribers routing
	subscriber := resources.Subscriber{}
	subscribers := router.Group(subscriber.BasePath())
	{
		subscribers.Use(middlewares.JsonAPI(&subscriber)).POST("", handlers.CreateSubscriber)
	}

The JsonAPI middleware:

const RESOURCE_CONTEXT = "resource"

func JsonAPI(r resources.APIResource) gin.HandlerFunc {
	return func(c *gin.Context) {
		if err := jsonapi.UnmarshalPayload(c.Request.Body, r); err != nil {
			responder.ErrorResponse(c, http.StatusBadRequest, []error{errors.New("Invalid JSON")})
			c.Abort()
			return
		}
		c.Set(RESOURCE_CONTEXT, r)
		c.Next()
	}
}

Then in my handler I can get the unmarshaled struct doing that:

subscriber := c.MustGet(middlewares.RESOURCE_CONTEXT).(*resources.Subscriber)

I really like this pattern as it makes my deserializing logic reusable but I'm going to add my own logic for validation too and it does not make sense as Gin binding are supposed to be the right way.

@takanuva15
Copy link
Contributor

takanuva15 commented Dec 19, 2024

Just wanted to add some extra details since I found this issue from google and it's been 7 years:

  • PR [Feature]: Support custom json codec at runtime #3391 has been opened to customize the entire marshal/unmarshal process in Gin
  • As an alternate solution to the above, you can also customize how json serialization occurs by defining a custom renderer and then passing that to the c.Render function. There is a detailed comment here.
    • Basically, instead of calling c.JSON, you would call c.Render(200, WithJSONv2(res)). (The implementation of WithJSONv2 is in the linked comment)
    • Note: This doesn't apply globally, so you would need to invoke it wherever you are returning a response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants