상세 컨텐츠

본문 제목

[Nomad Coin] Rest API - #6.1 Marshal and Field Tags

Go/Blockchain

by Gopythor 2022. 7. 20. 03:32

본문

728x90
반응형

#6.1 Marshal and Field Tags

  • 이 JSON을 유저에게 전달하고, 코드를 한 줄로 줄여볼 것이다.
  • Go가 struct을 Json으로 바꾸는 방식을 어떻게 바꿀 수 있는지도 볼 것이다.
  • 우선 PrintF를 Fprintf로 바꾸자. 콘솔이 아닌 writer에 작성하고 싶을 때 쓰는 것이다.

  • Fprintf를 쓰면 writer와 text를 받고 format 그리고 value를 받는다.
func documentation(rw http.ResponseWriter, r *http.Request) {
	data := []URLDescription{
		{
			URL:         "/",
			Method:      "GET",
			Description: "See Documentation",
		},
	}
	b, err := json.Marshal(data)
	utils.HandelErr(err)
	fmt.Fprintf(rw, "%s", b)
}
  • Fprintf에 writer를 작성하고, string화된 (%s) data를 보낼 것이다.

  • 사실 이건 JSON API가 아니다.
  • 이렇게 깔끔하게 볼 수 있는 이유는 JSON view라는 확장프로그램을 쓰기 때문이다(위의 스샷과는 다름)
  • 무언가가 JSON의 형태를 하고 있으면 깔끔하게 보여준다.

  • 파이어폭스에서 localhost:4000으로 URL을 가보면 위와 같이 텍스트를 return한다.
  • localhost의 request를 보면 content-type이 text로 되어 있는데 수정해야 한다.
  • JSON을 보내는 것 까지 했고, 이제 브라우저에게 JSON이라는 것을 알려야 한다.
  • Content-type를 바꿔야하니 복사하고 header를 수정할 것이다. header가 이럴때 쓰인다.

  • rw를 쓰면 우리가 할 수 있는 모든 것을 볼 수 있다.

  • Add()를 쓰자. Key와 value 두 개의 argument가 있다.
func documentation(rw http.ResponseWriter, r *http.Request) {
	data := []URLDescription{
		{
			URL:         "/",
			Method:      "GET",
			Description: "See Documentation",
		},
	}
	rw.Header().Add("Content-Type", "application/json")
	b, err := json.Marshal(data)
	utils.HandleErr(err)
	fmt.Fprintf(rw, "%s", b)
}
  • key는 Content-Type이고 value는 application/json이다.
  • 이제 제대로 json response를 보내는 것이다.

  • 웹사이트가 JSON이라고 말해줘야 JSON을 보여준다.
  • raw data는 텍스트처럼 보이지만 브라우저에 따라 JSON을 다르게 보여주기도 한다.
  • go를 쓰다보면 marshal, unmarshal을 많이 보게 될 것이다.

 

  • 더 쉬운 방법이 있는데, json.NewEncoder()를 입력하라. 이건 writer를 받는다.
  • NewEncoder는 writer에 작성하는 encoder를 return해준다고 쓰여 있다.

  • Encode라는 옵션이 있는데 Go의 interface를 받는다(강의는 interface()로 되어있다.).
func documentation(rw http.ResponseWriter, r *http.Request) {
	data := []URLDescription{
		{
			URL:         "/",
			Method:      "GET",
			Description: "See Documentation",
		},
	}
	rw.Header().Add("Content-Type", "application/json")
	json.NewEncoder(rw).Encode(data)
}
  • 여기에 data를 넣는다.
  • 원래 했던 세 줄의 코드와 같다.

  • 저장하고 서버 종료한 다음 다시 해보면 똑같이 작동할 것이다.
  • Headers에 보면 똑같다.

 

  • 이제 struct field tags에 대해 이야기해보자.
  • struct field tag는 기본적으로 struct가 json으로 변환하는 방식을 바꾸는 방법이다
  • 구체적으로 이름을 뜻한다.
  • 대문자로 시작하는 Method를 사용하고 싶지 않다고 해볼 때, 보통 json API는 대문자를 안쓰고 소문자만 쓴다.
type URLDescription struct {
	URL         string
	method      string
	Description string
}

func documentation(rw http.ResponseWriter, r *http.Request) {
	data := []URLDescription{
		{
			URL:         "/",
			method:      "GET",
			Description: "See Documentation",
		},
	}
	rw.Header().Add("Content-Type", "application/json")
	json.NewEncoder(rw).Encode(data)
}
  • 소문자로 된 method를 사용하고 싶다면 이렇게 하면 된다고 생각할 것이다.
  • 그런데 이렇게 하면 Go의 법칙에 따라 소문자는 export하지 않는다.

  • method가 없다.써어놓긴 했지만 소문자라서 없는 것이다.
  • 하지만 API에서 대문자를 사용하지 않고 그냥 쓰고 싶다면 어떻게 하는가?
  • 소문자로 쓰면 export되지 않기 때문에 소문자를 쓸 수 없다.
type URLDescription struct {
	URL         string `json:"url"`
	Method      string `json:"method"`
	Description string `json:"description"`
}
  • 이때 struct field tag를 대신 사용한다.
  • 대문자는 그대로 두고 struct field tag를 써주는 것이다.
  • 중요한 점은 백틱(``)과 큰따옴표("")를 같이 써줘야 한다.
  • struct가 json이라면, Field가 특정한 방식으로 보여질 것이라고 설정할 수 있다.
  • 대문자 URL이 소문자 url로 된다.
  • Method도 마찬가지로, json이면 소문자 method로
  • json이면 description으로
  • 이 syntax는 특이하다. `json: "url"`

  • 친 API적인 모습이 되었다.
  • omitempty라는 것도 있다. Field가 비어있으면 Field를 숨겨준다.
type URLDescription struct {
	URL         string `json:"url"`
	Method      string `json:"method"`
	Description string `json:"description"`
	Payload     string `json:"payload,omitempty"`
}
  • 예를 들어 payload를 써보자. 네가 보내줘야 하는 것
  • `json:"payload, omitempty"`를 써주자.
  • 이게 중요한 이유는 어떤 것은 payload가 없을 수도 있다.
{
	URL:         "/",
	Method:      "GET",
	Description: "See Documentation",
},
  • 예를들어 여기에는 payload가 필요 없지만, URL:"/blocks", Method: "POST", Description:"Add a block"이고
{
	URL:         "/blocks",
	Method:      "POST",
	Description: "Add A Block",
	Payload:     "data:string",
	},
  • Payload는 네가 블록을 만들고 싶다면, /blocks URL로 POST request와 body에는 data:string이 있어야 한다.

  • omitempty때문에 첫 번째에는 payload가 없다.
type URLDescription struct {
	URL         string `json:"url"`
	Method      string `json:"method"`
	Description string `json:"description"`
	Payload     string `json:"payload"`
}

  • 이걸 지우고 다시 확인해보면, 비어있는 payload가 있다.
  • Go에서 struct가 json으로 변하면 어떻게 보일지 조정할 수 있다.
  • 만약 Field를 무시하고 싶으면 `json:"-"`를 해주면 된다. 이게 field를 무시하게 해준다.

 

 

  • json은 그냥 텍스트지만 Content-Type을 보내는 순간 모든게 변한다.
  • 중요한 Marshal에 대해서도 배웠지만, 더 간단한 방법이 있었다. writer에 작성할 대 특히나.
  • 만약 다른 작업을 하는데 json을 다른 방식으로 보내야 하고 writer가 없다면 Marshal을 쓰고 그 data를 보낼 것이다.
  • Encoder가 최선의 방법이다. encoder는 writer를 받고 data를 무료로 encode해준다.
  • Encode를 확인해보면 어떤 방식으로든 Marshal을 사용하고 있을 것이다.
728x90
반응형

관련글 더보기

댓글 영역