gin
gin copied to clipboard
feat(binding): add support for encoding.UnmarshalText in uri/query binding
With this PR, users can now specify parser=encoding.TextUnmarshaler in their form/uri tag to enable automatic binding using the encoding.TextUnmarshaler interface from the Golang standard library. Since this new parser tag is 100% opt-in only, this is fully backwards-compatible with previous versions of gin.
Merging this PR will resolve a number of tickets regarding this functionality:
- https://github.com/gin-gonic/gin/issues/4177
- https://github.com/gin-gonic/gin/pull/3933#issuecomment-2692206957
- https://github.com/gin-gonic/gin/pull/3045
closes #4177
Sample code to run:
package main
import (
"encoding"
"strings"
"github.com/gin-gonic/gin"
)
type Birthday string
func (b *Birthday) UnmarshalText(text []byte) error {
*b = Birthday(strings.Replace(string(text), "-", "/", -1))
return nil
}
var _ encoding.TextUnmarshaler = (*Birthday)(nil) //assert Birthday implements encoding.TextUnmarshaler
func main() {
route := gin.Default()
var request struct {
Birthday Birthday `form:"birthday,parser=encoding.TextUnmarshaler"`
Birthdays []Birthday `form:"birthdays,parser=encoding.TextUnmarshaler" collection_format:"csv"`
BirthdaysDefault []Birthday `form:"birthdaysDef,default=2020-09-01;2020-09-02,parser=encoding.TextUnmarshaler" collection_format:"csv"`
}
route.GET("/test", func(ctx *gin.Context) {
_ = ctx.BindQuery(&request)
ctx.JSON(200, request)
})
_ = route.Run(":8088")
}
Test it with:
curl 'localhost:8088/test?birthday=2000-01-01&birthdays=2000-01-01,2000-01-02'
Result
{"Birthday":"2000/01/01","Birthdays":["2000/01/01","2000/01/02"],"BirthdaysDefault":["2020/09/01","2020/09/02"]
Codecov Report
:white_check_mark: All modified and coverable lines are covered by tests.
:white_check_mark: Project coverage is 98.82%. Comparing base (3dc1cd6) to head (8a07c82).
:warning: Report is 187 commits behind head on master.
Additional details and impacted files
@@ Coverage Diff @@
## master #4203 +/- ##
==========================================
- Coverage 99.21% 98.82% -0.40%
==========================================
Files 42 44 +2
Lines 3182 3484 +302
==========================================
+ Hits 3157 3443 +286
- Misses 17 30 +13
- Partials 8 11 +3
| Flag | Coverage Δ | |
|---|---|---|
? |
||
| --ldflags="-checklinkname=0" -tags sonic | 98.81% <100.00%> (?) |
|
| -tags go_json | 98.75% <100.00%> (?) |
|
| -tags nomsgpack | 98.80% <100.00%> (?) |
|
| go-1.18 | ? |
|
| go-1.19 | ? |
|
| go-1.20 | ? |
|
| go-1.21 | ? |
|
| go-1.24 | 98.82% <100.00%> (?) |
|
| go-1.25 | 98.82% <100.00%> (?) |
|
| macos-latest | 98.82% <100.00%> (-0.40%) |
:arrow_down: |
| ubuntu-latest | 98.82% <100.00%> (-0.40%) |
:arrow_down: |
Flags with carried forward coverage won't be shown. Click here to find out more.
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
@appleboy ready for review. I verified locally that all my new changes are covered with the new tests I added. The linting failure is unrelated to my changes since I did not add any sprintf calls to my code
Please rebase the master branch. @takanuva15
@appleboy done, just rebased it now
I'm not sure why the coverage shows as dropped, but I just ran a full coverage report via
go test -cover -coverprofile=c.out ./... -coverpkg=./... \
&& go tool cover -html=c.out -o coverage.html
and it shows 100% coverage on form_mapping.go, which is the only file I modified.
@takanuva15 Please help to resolve the conflicts.
@takanuva15 Please help to resolve the conflicts.
done
I will take it.