bkdragon's log

[gin] JSON 본문

golang

[gin] JSON

bkdragon 2024. 9. 8. 15:37

gin Context 에 있는 JSON 메서드는 json 응답을 빼주는 데 사용한다. 내부 구현을 살펴보자.

func (c *Context) JSON(code int, obj any) {
    c.Render(code, render.JSON{Data: obj})
}

JSON 은 Render라는 메서드를 호출하는데, 상태 코드와 render.JSON을 구조체를 인자로 받는다.

c.Render를 먼저 살펴보면

func (c *Context) Render(code int, r render.Render) {
    c.Status(code)

    if !bodyAllowedForStatus(code) {
        r.WriteContentType(c.Writer)
        c.Writer.WriteHeaderNow()
        return
    }

    if err := r.Render(c.Writer); err != nil {
        // Pushing error to c.Errors
        _ = c.Error(err)
        c.Abort()
    }
}

눈치가 빠르다면 메서드의 시그니처를 보고 Render 는 인터페이스이고 JSON 구조체가 Render의 구현체이라는 것을 알 수 있다.

팩트일지 체크해보자.

type Render interface {
    // Render writes data with custom ContentType.
    Render(http.ResponseWriter) error
    // WriteContentType writes custom ContentType.
    WriteContentType(w http.ResponseWriter)
}

우선 인터페이스는 맞다. Render, WriteContentType 메서드를 가지고 있다.

type JSON struct {
    Data any
}

JSON 은 우선 데이터라는 속성을 가지고 있고,

// Render (JSON) writes data with custom ContentType.
func (r JSON) Render(w http.ResponseWriter) error {
    return WriteJSON(w, r.Data)
}

// WriteContentType (JSON) writes JSON ContentType.
func (r JSON) WriteContentType(w http.ResponseWriter) {
    writeContentType(w, jsonContentType)
}

이렇게 Render, WriteContentType 메서드를 가지고 있다. 눈치게임 성공이다.

WriteJson에 응답을 쓰는 코드가 작성되어있을 것이다.

func WriteJSON(w http.ResponseWriter, obj any) error {
    writeContentType(w, jsonContentType)
    jsonBytes, err := json.Marshal(obj)
    if err != nil {
        return err
    }
    _, err = w.Write(jsonBytes)
    return err
}

Marshal 하고 Write 하는 걸 확인할 수 있다.

근데 ShouldBindJSON 메서드와는 다르게 스트림 방식을 사용하진 않는다.

스트림 방식으로 변경을 한번 해보자.

func WriteJSON(w http.ResponseWriter, obj any) error {
    writeContentType(w, jsonContentType)
    encoder := json.NewEncoder(w)
    return encoder.Encode(obj)
}

good!

'golang' 카테고리의 다른 글

[gin] Clean Architecture  (1) 2024.09.20
[gorm] 다형성 관계  (0) 2024.09.11
[go] http 통신 과정  (0) 2024.09.10
[gin] ShouldBindJSON  (0) 2024.09.08
[go] io 패키지  (5) 2024.09.07