Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 티스토리챌린지
- JavaSpring
- hook
- Chakra
- Gin
- backend
- typescript
- Redux
- RTK
- 오블완
- JPA
- react-hook-form
- springboot
- java
- React
- designpatterns
- 웹애플리케이션서버
- tanstackquery
- go
- ReactHooks
- css
- javascript
- component
- storybook
- golang
- test
- frontend
- satisfiles
- Spring
Archives
- Today
- Total
bkdragon's log
[gin] ShouldBindJSON 본문
gin 의 Context 에 있는 ShouldBindJSON 메서드는 JSON 데이터를 구조체로 바꿔주는 역할을 한다. 아마 요청을 읽고 Unmarshal 하는 과정이 있지 않을까 싶은데 실제 구현이 궁금해서 코드를 좀 찾아보았다.
func (c *Context) ShouldBindJSON(obj any) error {
return c.ShouldBindWith(obj, binding.JSON)
}
func (c *Context) ShouldBindWith(obj any, b binding.Binding) error {
return b.Bind(c.Request, obj)
}
ShouldBindJSON 는 ShouldBindWith 를 호출한다. ShouldBindWith 는 Binding 구조체와 obj를 받아서 Bind를 호출한다.
Binding 구조체를 살펴보자.
type Binding interface {
Name() string
Bind(*http.Request, any) error
}
인터페이스였다. Bind 메서드를 가지고 있다. 이제 구현체를 찾아보자.
var (
JSON BindingBody = jsonBinding{}
XML BindingBody = xmlBinding{}
Form Binding = formBinding{}
Query Binding = queryBinding{}
FormPost Binding = formPostBinding{}
FormMultipart Binding = formMultipartBinding{}
ProtoBuf BindingBody = protobufBinding{}
MsgPack BindingBody = msgpackBinding{}
YAML BindingBody = yamlBinding{}
Uri BindingUri = uriBinding{}
Header Binding = headerBinding{}
TOML BindingBody = tomlBinding{}
)
포맷에 따라 다양한 구현체가 구현되어있다. 아까 binding.JSON 을 ShouldBindWith 에 넘기고 있었는데 이 구현체를 넘긴것이였다.
jsonBinding 구조체를 확인해보면 Name과 Bind 메서드를 가지고 있을 것이다.
type jsonBinding struct{}
func (jsonBinding) Name() string {
return "json"
}
func (jsonBinding) Bind(req *http.Request, obj any) error {
if req == nil || req.Body == nil {
return errors.New("invalid request")
}
return decodeJSON(req.Body, obj)
}
func (jsonBinding) BindBody(body []byte, obj any) error {
return decodeJSON(bytes.NewReader(body), obj)
}
func decodeJSON(r io.Reader, obj any) error {
decoder := json.NewDecoder(r)
if EnableDecoderUseNumber {
decoder.UseNumber()
}
if EnableDecoderDisallowUnknownFields {
decoder.DisallowUnknownFields()
}
if err := decoder.Decode(obj); err != nil {
return err
}
return validate(obj)
}
빙고!
Name은 단순히 json이라는 문자열을 리턴해주고 있다. Bind는 예상과는 다르게 decoder 를 사용해서 스트림 방식으로 데이터를 처리한다. 이 방식은 메모리를 사용하지 않기 때문에 대용량 요청일 수록 성능적으로 이점이 있다.
'golang' 카테고리의 다른 글
[gin] Clean Architecture (1) | 2024.09.20 |
---|---|
[gorm] 다형성 관계 (0) | 2024.09.11 |
[go] http 통신 과정 (0) | 2024.09.10 |
[gin] JSON (1) | 2024.09.08 |
[go] io 패키지 (5) | 2024.09.07 |