Skip to content

feat(binding): use encoding.UnmarshalText by default via build tag#4566

Open
takanuva15 wants to merge 2 commits intogin-gonic:masterfrom
takanuva15:feature/enable-default-unmarshaltext
Open

feat(binding): use encoding.UnmarshalText by default via build tag#4566
takanuva15 wants to merge 2 commits intogin-gonic:masterfrom
takanuva15:feature/enable-default-unmarshaltext

Conversation

@takanuva15
Copy link
Contributor

With this PR, users can set the build tag gin_bind_encoding to configure gin binding to use encoding.UnmarshalText by default. This will not break existing servers since the build tag must be specified to enable the behavior.

Credit to #4540 for the original default binding implementation

relates to #4540
relates to #4203
relates to #4177
relates to #3933
relates to #3045
relates to #3036
relates to #2673
relates to #2631
relates to #2510
closes #2423
closes #3060

Example

package main

import (
  "github.com/gin-gonic/gin"
  "github.com/gofrs/uuid"
)

func main() {
  route := gin.Default()
  var request struct {
    Uuid uuid.UUID `form:"uuid" binding:"uuid"`
  }

  route.GET("/test", func(ctx *gin.Context) {
    _ = ctx.BindQuery(&request)
    ctx.JSON(200, request)
  })
  _ = route.Run(":8088")
}

Test it with:

go run -tags=gin_bind_encoding main.go
# Then in another terminal
curl 'localhost:8088/test?uuid=70d9b500-fa26-11dd-876f-322495cdf0f7'

Result

{"Uuid":"70d9b500-fa26-11dd-876f-322495cdf0f7"}

Pull Request Checklist

Please ensure your pull request meets the following requirements:

  • Open your pull request against the master branch.
  • All tests pass in available continuous integration systems (e.g., GitHub Actions).
  • Tests are added or modified as needed to cover code changes.
  • If the pull request introduces a new feature, the feature is documented in the docs/doc.md.

Thank you for contributing!

Types like uuid.UUID implement encoding.TextUnmarshaler but previously
required an explicit `parser=encoding.TextUnmarshaler` struct tag to be
used during form/query/URI binding. This meant ShouldBind/ShouldBindQuery
would fail with unhelpful errors like:
  ["45e1f85e-bca5-458d-bd9c-c56edd8f847b"] is not valid value for uuid.UUID

This change makes trySetCustom automatically check for
encoding.TextUnmarshaler as a fallback after BindUnmarshaler,
so any type implementing TextUnmarshaler (uuid.UUID, net.IP,
custom types, etc.) works out of the box with no extra tags.

Precedence order:
1. BindUnmarshaler (UnmarshalParam)
2. encoding.TextUnmarshaler (UnmarshalText)
3. Default type-based binding

time.Time is explicitly excluded from automatic TextUnmarshaler
handling since gin has dedicated time parsing with time_format,
time_utc, and time_location struct tags.

Fixes gin-gonic#2423

Signed-off-by: Varun Chawla <varun_6april@hotmail.com>
@takanuva15 takanuva15 force-pushed the feature/enable-default-unmarshaltext branch from 59b827d to 513eec4 Compare March 6, 2026 19:47
@codecov
Copy link

codecov bot commented Mar 6, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.31%. Comparing base (3dc1cd6) to head (07bcf34).
⚠️ Report is 268 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4566      +/-   ##
==========================================
- Coverage   99.21%   98.31%   -0.90%     
==========================================
  Files          42       51       +9     
  Lines        3182     3152      -30     
==========================================
- Hits         3157     3099      -58     
- Misses         17       44      +27     
- Partials        8        9       +1     
Flag Coverage Δ
?
--ldflags="-checklinkname=0" -tags sonic 98.30% <100.00%> (?)
-tags gin_bind_encoding 98.30% <100.00%> (?)
-tags go_json 98.23% <100.00%> (?)
-tags nomsgpack 98.28% <100.00%> (?)
go-1.18 ?
go-1.19 ?
go-1.20 ?
go-1.21 ?
go-1.25 98.31% <100.00%> (?)
go-1.26 98.31% <100.00%> (?)
macos-latest 98.31% <100.00%> (-0.90%) ⬇️
ubuntu-latest 98.31% <100.00%> (-0.90%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@takanuva15 takanuva15 force-pushed the feature/enable-default-unmarshaltext branch 3 times, most recently from 29f5df0 to bee5bd3 Compare March 6, 2026 22:13
@takanuva15 takanuva15 force-pushed the feature/enable-default-unmarshaltext branch from bee5bd3 to 07bcf34 Compare March 9, 2026 21:33
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

Successfully merging this pull request may close these issues.

Bind with query param fails with uuid.UUID and uuid.NullUUID Binding uuid.UUID using ShouldBind

2 participants