Skip to content

Commit 7a865dc

Browse files
feat(bind): ShouldBindBodyWith shortcut and change doc (#3871)
* feat: ShouldBindBodyWith shortcut and change doc * fix: yaml can parse json test case * style: fix new test case in context_test.go * chore: modify the code style to specify binding type * chroe: gofmt modifies the code format
1 parent fd1faad commit 7a865dc

File tree

3 files changed

+284
-2
lines changed

3 files changed

+284
-2
lines changed

context.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,26 @@ func (c *Context) ShouldBindBodyWith(obj any, bb binding.BindingBody) (err error
774774
return bb.BindBody(body, obj)
775775
}
776776

777+
// ShouldBindBodyWithJSON is a shortcut for c.ShouldBindBodyWith(obj, binding.JSON).
778+
func (c *Context) ShouldBindBodyWithJSON(obj any) error {
779+
return c.ShouldBindBodyWith(obj, binding.JSON)
780+
}
781+
782+
// ShouldBindBodyWithXML is a shortcut for c.ShouldBindBodyWith(obj, binding.XML).
783+
func (c *Context) ShouldBindBodyWithXML(obj any) error {
784+
return c.ShouldBindBodyWith(obj, binding.XML)
785+
}
786+
787+
// ShouldBindBodyWithYAML is a shortcut for c.ShouldBindBodyWith(obj, binding.YAML).
788+
func (c *Context) ShouldBindBodyWithYAML(obj any) error {
789+
return c.ShouldBindBodyWith(obj, binding.YAML)
790+
}
791+
792+
// ShouldBindBodyWithTOML is a shortcut for c.ShouldBindBodyWith(obj, binding.TOML).
793+
func (c *Context) ShouldBindBodyWithTOML(obj any) error {
794+
return c.ShouldBindBodyWith(obj, binding.TOML)
795+
}
796+
777797
// ClientIP implements one best effort algorithm to return the real client IP.
778798
// It calls c.RemoteIP() under the hood, to check if the remote IP is a trusted proxy or not.
779799
// If it is it will then try to parse the headers defined in Engine.RemoteIPHeaders (defaulting to [X-Forwarded-For, X-Real-Ip]).

context_test.go

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,6 +1977,263 @@ func TestContextShouldBindBodyWith(t *testing.T) {
19771977
}
19781978
}
19791979

1980+
func TestContextShouldBindBodyWithJSON(t *testing.T) {
1981+
for _, tt := range []struct {
1982+
name string
1983+
bindingBody binding.BindingBody
1984+
body string
1985+
}{
1986+
{
1987+
name: " JSON & JSON-BODY ",
1988+
bindingBody: binding.JSON,
1989+
body: `{"foo":"FOO"}`,
1990+
},
1991+
{
1992+
name: " JSON & XML-BODY ",
1993+
bindingBody: binding.XML,
1994+
body: `<?xml version="1.0" encoding="UTF-8"?>
1995+
<root>
1996+
<foo>FOO</foo>
1997+
</root>`,
1998+
},
1999+
{
2000+
name: " JSON & YAML-BODY ",
2001+
bindingBody: binding.YAML,
2002+
body: `foo: FOO`,
2003+
},
2004+
{
2005+
name: " JSON & TOM-BODY ",
2006+
bindingBody: binding.TOML,
2007+
body: `foo=FOO`,
2008+
},
2009+
} {
2010+
t.Logf("testing: %s", tt.name)
2011+
2012+
w := httptest.NewRecorder()
2013+
c, _ := CreateTestContext(w)
2014+
2015+
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(tt.body))
2016+
2017+
type typeJSON struct {
2018+
Foo string `json:"foo" binding:"required"`
2019+
}
2020+
objJSON := typeJSON{}
2021+
2022+
if tt.bindingBody == binding.JSON {
2023+
assert.NoError(t, c.ShouldBindBodyWithJSON(&objJSON))
2024+
assert.Equal(t, typeJSON{"FOO"}, objJSON)
2025+
}
2026+
2027+
if tt.bindingBody == binding.XML {
2028+
assert.Error(t, c.ShouldBindBodyWithJSON(&objJSON))
2029+
assert.Equal(t, typeJSON{}, objJSON)
2030+
}
2031+
2032+
if tt.bindingBody == binding.YAML {
2033+
assert.Error(t, c.ShouldBindBodyWithJSON(&objJSON))
2034+
assert.Equal(t, typeJSON{}, objJSON)
2035+
}
2036+
2037+
if tt.bindingBody == binding.TOML {
2038+
assert.Error(t, c.ShouldBindBodyWithJSON(&objJSON))
2039+
assert.Equal(t, typeJSON{}, objJSON)
2040+
}
2041+
}
2042+
}
2043+
2044+
func TestContextShouldBindBodyWithXML(t *testing.T) {
2045+
for _, tt := range []struct {
2046+
name string
2047+
bindingBody binding.BindingBody
2048+
body string
2049+
}{
2050+
{
2051+
name: " XML & JSON-BODY ",
2052+
bindingBody: binding.JSON,
2053+
body: `{"foo":"FOO"}`,
2054+
},
2055+
{
2056+
name: " XML & XML-BODY ",
2057+
bindingBody: binding.XML,
2058+
body: `<?xml version="1.0" encoding="UTF-8"?>
2059+
<root>
2060+
<foo>FOO</foo>
2061+
</root>`,
2062+
},
2063+
{
2064+
name: " XML & YAML-BODY ",
2065+
bindingBody: binding.YAML,
2066+
body: `foo: FOO`,
2067+
},
2068+
{
2069+
name: " XML & TOM-BODY ",
2070+
bindingBody: binding.TOML,
2071+
body: `foo=FOO`,
2072+
},
2073+
} {
2074+
t.Logf("testing: %s", tt.name)
2075+
2076+
w := httptest.NewRecorder()
2077+
c, _ := CreateTestContext(w)
2078+
2079+
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(tt.body))
2080+
2081+
type typeXML struct {
2082+
Foo string `xml:"foo" binding:"required"`
2083+
}
2084+
objXML := typeXML{}
2085+
2086+
if tt.bindingBody == binding.JSON {
2087+
assert.Error(t, c.ShouldBindBodyWithXML(&objXML))
2088+
assert.Equal(t, typeXML{}, objXML)
2089+
}
2090+
2091+
if tt.bindingBody == binding.XML {
2092+
assert.NoError(t, c.ShouldBindBodyWithXML(&objXML))
2093+
assert.Equal(t, typeXML{"FOO"}, objXML)
2094+
}
2095+
2096+
if tt.bindingBody == binding.YAML {
2097+
assert.Error(t, c.ShouldBindBodyWithXML(&objXML))
2098+
assert.Equal(t, typeXML{}, objXML)
2099+
}
2100+
2101+
if tt.bindingBody == binding.TOML {
2102+
assert.Error(t, c.ShouldBindBodyWithXML(&objXML))
2103+
assert.Equal(t, typeXML{}, objXML)
2104+
}
2105+
}
2106+
}
2107+
2108+
func TestContextShouldBindBodyWithYAML(t *testing.T) {
2109+
for _, tt := range []struct {
2110+
name string
2111+
bindingBody binding.BindingBody
2112+
body string
2113+
}{
2114+
{
2115+
name: " YAML & JSON-BODY ",
2116+
bindingBody: binding.JSON,
2117+
body: `{"foo":"FOO"}`,
2118+
},
2119+
{
2120+
name: " YAML & XML-BODY ",
2121+
bindingBody: binding.XML,
2122+
body: `<?xml version="1.0" encoding="UTF-8"?>
2123+
<root>
2124+
<foo>FOO</foo>
2125+
</root>`,
2126+
},
2127+
{
2128+
name: " YAML & YAML-BODY ",
2129+
bindingBody: binding.YAML,
2130+
body: `foo: FOO`,
2131+
},
2132+
{
2133+
name: " YAML & TOM-BODY ",
2134+
bindingBody: binding.TOML,
2135+
body: `foo=FOO`,
2136+
},
2137+
} {
2138+
t.Logf("testing: %s", tt.name)
2139+
2140+
w := httptest.NewRecorder()
2141+
c, _ := CreateTestContext(w)
2142+
2143+
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(tt.body))
2144+
2145+
type typeYAML struct {
2146+
Foo string `yaml:"foo" binding:"required"`
2147+
}
2148+
objYAML := typeYAML{}
2149+
2150+
// YAML belongs to a super collection of JSON, so JSON can be parsed by YAML
2151+
if tt.bindingBody == binding.JSON {
2152+
assert.NoError(t, c.ShouldBindBodyWithYAML(&objYAML))
2153+
assert.Equal(t, typeYAML{"FOO"}, objYAML)
2154+
}
2155+
2156+
if tt.bindingBody == binding.XML {
2157+
assert.Error(t, c.ShouldBindBodyWithYAML(&objYAML))
2158+
assert.Equal(t, typeYAML{}, objYAML)
2159+
}
2160+
2161+
if tt.bindingBody == binding.YAML {
2162+
assert.NoError(t, c.ShouldBindBodyWithYAML(&objYAML))
2163+
assert.Equal(t, typeYAML{"FOO"}, objYAML)
2164+
}
2165+
2166+
if tt.bindingBody == binding.TOML {
2167+
assert.Error(t, c.ShouldBindBodyWithYAML(&objYAML))
2168+
assert.Equal(t, typeYAML{}, objYAML)
2169+
}
2170+
}
2171+
}
2172+
2173+
func TestContextShouldBindBodyWithTOML(t *testing.T) {
2174+
for _, tt := range []struct {
2175+
name string
2176+
bindingBody binding.BindingBody
2177+
body string
2178+
}{
2179+
{
2180+
name: " TOML & JSON-BODY ",
2181+
bindingBody: binding.JSON,
2182+
body: `{"foo":"FOO"}`,
2183+
},
2184+
{
2185+
name: " TOML & XML-BODY ",
2186+
bindingBody: binding.XML,
2187+
body: `<?xml version="1.0" encoding="UTF-8"?>
2188+
<root>
2189+
<foo>FOO</foo>
2190+
</root>`,
2191+
},
2192+
{
2193+
name: " TOML & YAML-BODY ",
2194+
bindingBody: binding.YAML,
2195+
body: `foo: FOO`,
2196+
},
2197+
{
2198+
name: " TOML & TOM-BODY ",
2199+
bindingBody: binding.TOML,
2200+
body: `foo = 'FOO'`,
2201+
},
2202+
} {
2203+
t.Logf("testing: %s", tt.name)
2204+
2205+
w := httptest.NewRecorder()
2206+
c, _ := CreateTestContext(w)
2207+
2208+
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(tt.body))
2209+
2210+
type typeTOML struct {
2211+
Foo string `toml:"foo" binding:"required"`
2212+
}
2213+
objTOML := typeTOML{}
2214+
2215+
if tt.bindingBody == binding.JSON {
2216+
assert.Error(t, c.ShouldBindBodyWithTOML(&objTOML))
2217+
assert.Equal(t, typeTOML{}, objTOML)
2218+
}
2219+
2220+
if tt.bindingBody == binding.XML {
2221+
assert.Error(t, c.ShouldBindBodyWithTOML(&objTOML))
2222+
assert.Equal(t, typeTOML{}, objTOML)
2223+
}
2224+
2225+
if tt.bindingBody == binding.YAML {
2226+
assert.Error(t, c.ShouldBindBodyWithTOML(&objTOML))
2227+
assert.Equal(t, typeTOML{}, objTOML)
2228+
}
2229+
2230+
if tt.bindingBody == binding.TOML {
2231+
assert.NoError(t, c.ShouldBindBodyWithTOML(&objTOML))
2232+
assert.Equal(t, typeTOML{"FOO"}, objTOML)
2233+
}
2234+
}
2235+
}
2236+
19802237
func TestContextGolangContext(t *testing.T) {
19812238
c, _ := CreateTestContext(httptest.NewRecorder())
19822239
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))

docs/doc.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1956,7 +1956,12 @@ func SomeHandler(c *gin.Context) {
19561956
}
19571957
```
19581958

1959-
For this, you can use `c.ShouldBindBodyWith`.
1959+
For this, you can use `c.ShouldBindBodyWith` or shortcuts.
1960+
1961+
- `c.ShouldBindBodyWithJSON` is a shortcut for c.ShouldBindBodyWith(obj, binding.JSON).
1962+
- `c.ShouldBindBodyWithXML` is a shortcut for c.ShouldBindBodyWith(obj, binding.XML).
1963+
- `c.ShouldBindBodyWithYAML` is a shortcut for c.ShouldBindBodyWith(obj, binding.YAML).
1964+
- `c.ShouldBindBodyWithTOML` is a shortcut for c.ShouldBindBodyWith(obj, binding.TOML).
19601965

19611966
```go
19621967
func SomeHandler(c *gin.Context) {
@@ -1969,7 +1974,7 @@ func SomeHandler(c *gin.Context) {
19691974
} else if errB := c.ShouldBindBodyWith(&objB, binding.JSON); errB == nil {
19701975
c.String(http.StatusOK, `the body should be formB JSON`)
19711976
// And it can accepts other formats
1972-
} else if errB2 := c.ShouldBindBodyWith(&objB, binding.XML); errB2 == nil {
1977+
} else if errB2 := c.ShouldBindBodyWithXML(&objB); errB2 == nil {
19731978
c.String(http.StatusOK, `the body should be formB XML`)
19741979
} else {
19751980
...

0 commit comments

Comments
 (0)