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.
Comment From: takanuva15
Just wanted to add some extra details since I found this issue from google and it's been 7 years:
- PR #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