Go를 사용하여 JSON 응답을 제공하는 방법은 무엇입니까?


99

질문 : 현재 다음 func Index 과 같이 내 응답을 인쇄하고 fmt.Fprintf(w, string(response)) 있지만 요청에서 JSON을 제대로 보내면보기에서 사용할 수 있습니까?

package main

import (
    "fmt"
    "github.com/julienschmidt/httprouter"
    "net/http"
    "log"
    "encoding/json"
)

type Payload struct {
    Stuff Data
}
type Data struct {
    Fruit Fruits
    Veggies Vegetables
}
type Fruits map[string]int
type Vegetables map[string]int


func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    response, err := getJsonResponse();
    if err != nil {
        panic(err)
    }
    fmt.Fprintf(w, string(response))
}


func main() {
    router := httprouter.New()
    router.GET("/", Index)
    log.Fatal(http.ListenAndServe(":8080", router))
}

func getJsonResponse()([]byte, error) {
    fruits := make(map[string]int)
    fruits["Apples"] = 25
    fruits["Oranges"] = 10

    vegetables := make(map[string]int)
    vegetables["Carrats"] = 10
    vegetables["Beets"] = 0

    d := Data{fruits, vegetables}
    p := Payload{d}

    return json.MarshalIndent(p, "", "  ")
}

github.com/unrolled/render 도 도움이 될 수 있습니다.
elithrar jul.

답변:


131

클라이언트가 json을 기대할 수 있도록 콘텐츠 유형 헤더를 설정할 수 있습니다.

w.Header().Set("Content-Type", "application/json")

구조체를 json으로 마샬링하는 또 다른 방법은 다음을 사용하여 인코더를 빌드하는 것입니다. http.ResponseWriter

// get a payload p := Payload{d}
json.NewEncoder(w).Encode(p)

11
w.Header().Set("Content-Type", "application/json")콘텐츠 유형을 설정하는 데는 정확 하지만 json.NewEncoder대신 사용할 때 txt / 일반 결과를 얻지 않습니다 . 다른 사람이 이것을 받고 있습니까? @poorva의 답변은 예상대로 작동했습니다
Jaybeecave 2017

2
스크래치. 내가 사용 w.WriteHeader(http.StatusOk) 하면 위의 결과를 얻습니다.
Jaybeecave 2017

4
내가 사용하는 경우 w.WriteHeader(http.StatusOk)다음 내가 얻을 text/plain; charset=utf-8내가 명시 적으로 내가 얻을 현상 코드를 설정 해달라고하는 경우, applicaton/json그리고 응답은 여전히 현상 코드 200가
라몬 람보

1
흠 ... 여기 문서와 관련이 있습니까? Changing the header map after a call to WriteHeader (or Write) has no effect unless the modified headers are trailers.
Dan Esparza

2
추가 w.Header().Set("Content-Type", "application/json")이상 json.NewEncoder(w).Encode(p)나를 위해 일
Ardi Nusawan

36

다른 사용자 Content-Typeplain/text인코딩 할 때가 있다고 언급합니다 . Content-Type먼저 w.Header().SetHTTP 응답 코드 를 설정해야 합니다 w.WriteHeader.

당신이 호출 할 경우 w.WriteHeader먼저 전화를 w.Header().Set당신이 얻을 것이다 후 plain/text.

예제 핸들러는 다음과 같습니다.

func SomeHandler(w http.ResponseWriter, r *http.Request) {
    data := SomeStruct{}
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusCreated)
    json.NewEncoder(w).Encode(data)
}

내 프로그램이 패닉 상태 인 경우 응답을 반환하는 방법은 무엇입니까? 나는 recover ()를 사용해 보았지만 돌아 왔지만 작동하지 않았습니다.
infiniteLearner

30

getJsonResponse함수 에서 이와 같은 일을 할 수 있습니다.

jData, err := json.Marshal(Data)
if err != nil {
    // handle error
}
w.Header().Set("Content-Type", "application/json")
w.Write(jData)

2
이 버전에 대한 한 가지 중요한 사항은 jData불필요하게 에서 바이트 슬라이스를 사용한다는 것 입니다. Data마샬링되는 데이터에 따라 임의의 크기가 될 수 있으므로 이것은 사소한 메모리 낭비가 될 수 있습니다. 마샬링 후 메모리에서 ResponseWriter스트림으로 복사 합니다. json.NewEncoder () 등을 사용하는 대답은 마샬링 된 JSON을 ResponseWriter(그 스트림에 ..) 직접 작성합니다 .
Jonno

1
나를 위해 일했습니다! 'w.WriteHeader (http.StatusCreated)'가 전후에 추가 될 때 문제가 발생했습니다.
darkdefender27 2014 년

1
이 같은 공포 후 반환 할 필요는 프로그램 종료하지
andersfylling

적어도이 솔루션은 후행를 추가 \ n하지 않는의 Encoder.Encode()기능
조나단 뮬러

@Jonno 당신이 맞지만 헤더를 작성하기 전에 인코딩이 잘되는지 확인할 수있는 유일한 대답입니다. 한 번 작성하면 변경할 수 있기 때문입니다!
Cirelli94

2

gobuffalo.io 프레임 워크에서 다음과 같이 작동하도록했습니다.

// say we are in some resource Show action
// some code is omitted
user := &models.User{}
if c.Request().Header.Get("Content-type") == "application/json" {
    return c.Render(200, r.JSON(user))
} else {
    // Make user available inside the html template
    c.Set("user", user)
    return c.Render(200, r.HTML("users/show.html"))
}

그런 다음 해당 리소스에 대한 JSON 응답을 얻으려면 "Content-type"을 "application / json"으로 설정해야하며 작동합니다.

Rails가 여러 응답 유형을 처리하는 더 편리한 방법을 가지고 있다고 생각합니다. 지금까지 gobuffalo에서 동일한 것을 보지 못했습니다.


0

패키지 렌더러를 사용할 수 있습니다 . 저는 이런 종류의 문제를 해결하기 위해 작성했으며 JSON, JSONP, XML, HTML 등을 제공하는 래퍼입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.