Programing

Go에서 JSON 포스트 요청 처리

lottogame 2020. 4. 21. 08:17
반응형

Go에서 JSON 포스트 요청 처리


그래서 나는 다음을 가지고 있습니다. 매우 해키처럼 보이고 Go는 이것보다 라이브러리를 더 잘 설계했다고 생각했지만 Go는 JSON 데이터의 POST 요청을 처리하는 예제를 찾을 수 없습니다. 그것들은 모두 POST 형식입니다.

다음은 요청 예입니다. curl -X POST -d "{\"test\": \"that\"}" http://localhost:8082/test

다음은 로그가 포함 된 코드입니다.

package main

import (
    "encoding/json"
    "log"
    "net/http"
)

type test_struct struct {
    Test string
}

func test(rw http.ResponseWriter, req *http.Request) {
    req.ParseForm()
    log.Println(req.Form)
    //LOG: map[{"test": "that"}:[]]
    var t test_struct
    for key, _ := range req.Form {
        log.Println(key)
        //LOG: {"test": "that"}
        err := json.Unmarshal([]byte(key), &t)
        if err != nil {
            log.Println(err.Error())
        }
    }
    log.Println(t.Test)
    //LOG: that
}

func main() {
    http.HandleFunc("/test", test)
    log.Fatal(http.ListenAndServe(":8082", nil))
}

더 좋은 방법이 있을까요? 모범 사례가 무엇인지 찾아내는 데 어려움을 겪었습니다.

Go는 검색 엔진에 Golang이라고도하며 여기에서 언급되어 다른 사람들이 찾을 수 있습니다.


json.Decoder대신에 사용하십시오 json.Unmarshal.

func test(rw http.ResponseWriter, req *http.Request) {
    decoder := json.NewDecoder(req.Body)
    var t test_struct
    err := decoder.Decode(&t)
    if err != nil {
        panic(err)
    }
    log.Println(t.Test)
}

에서 읽어야 req.Body합니다. ParseForm메소드는 req.Body표준 HTTP 인코딩 형식으로 읽은 후 구문 분석합니다. 원하는 것은 본문을 읽고 JSON 형식으로 구문 분석하는 것입니다.

코드가 업데이트되었습니다.

package main

import (
    "encoding/json"
    "log"
    "net/http"
    "io/ioutil"
)

type test_struct struct {
    Test string
}

func test(rw http.ResponseWriter, req *http.Request) {
    body, err := ioutil.ReadAll(req.Body)
    if err != nil {
        panic(err)
    }
    log.Println(string(body))
    var t test_struct
    err = json.Unmarshal(body, &t)
    if err != nil {
        panic(err)
    }
    log.Println(t.Test)
}

func main() {
    http.HandleFunc("/test", test)
    log.Fatal(http.ListenAndServe(":8082", nil))
}

나는이 정확한 문제로 나 자신을 미치게했다. 내 JSON Marshaller와 Unmarshaller가 내 Go 구조체를 채우지 않았습니다. 그런 다음 https://eager.io/blog/go-and-json 에서 해결책을 찾았습니다 .

"Go의 모든 구조체와 마찬가지로 첫 글자가 대문자 인 필드 만 JSON Marshaller와 같은 외부 프로그램에서 볼 수 있음을 기억하는 것이 중요합니다."

그 후, 나의 Marshaller와 Unmarshaller는 완벽하게 일했습니다!


json.Decoder선호해야하는 두 가지 이유 가 있습니다 json.Unmarshal-2013 년의 가장 인기있는 답변에서 다루지 않습니다 :

  1. 2018 년 2 월, 원하지 않는 JSON 입력 감지 문제를 해결 go 1.10하는 새로운 메소드 json.Decoder.DisallowUnknownFields ()도입되었습니다.
  2. req.Body이미입니다 io.Reader. json.Unmarshal스트림이 유효하지 않은 경우 전체 내용을 읽은 다음 수행 하면 리소스가 낭비됩니다 (예 : 10MB의 잘못된 JSON 블록). 요청 본문 json.Decoder스트림 으로 해석하면 유효하지 않은 JSON이 발견되면 초기 구문 분석 오류가 발생합니다. I / O 스트림을 실시간으로 처리하는 것이 선호되는 방법 입니다.

잘못된 사용자 입력 감지에 대한 일부 사용자 의견 해결 :

필수 필드 및 기타 위생 검사를 시행하려면 다음을 시도하십시오.

d := json.NewDecoder(req.Body)
d.DisallowUnknownFields() // catch unwanted fields

// anonymous struct type: handy for one-time use
t := struct {
    Test *string `json:"test"` // pointer so we can test for field absence
}{}

err := d.Decode(&t)
if err != nil {
    // bad JSON or unrecognized json field
    http.Error(rw, err.Error(), http.StatusBadRequest)
    return
}

if t.Test == nil {
    http.Error(rw, "missing field 'test' from JSON object", http.StatusBadRequest)
    return
}

// optional extra check
if d.More() {
    http.Error(rw, "extraneous data after JSON object", http.StatusBadRequest)
    return
}

// got the input we expected: no more, no less
log.Println(*t.Test)

운동장

일반적인 출력 :

$ curl -X POST -d "{}" http://localhost:8082/strict_test

expected json field 'test'

$ curl -X POST -d "{\"Test\":\"maybe?\",\"Unwanted\":\"1\"}" http://localhost:8082/strict_test

json: unknown field "Unwanted"

$ curl -X POST -d "{\"Test\":\"oops\"}g4rB4g3@#$%^&*" http://localhost:8082/strict_test

extraneous data after JSON

$ curl -X POST -d "{\"Test\":\"Works\"}" http://localhost:8082/strict_test 

log: 2019/03/07 16:03:13 Works

도움이되는 문서에서 다음 예제를 찾았습니다 (source here ).

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "log"
    "strings"
)

func main() {
    const jsonStream = `
        {"Name": "Ed", "Text": "Knock knock."}
        {"Name": "Sam", "Text": "Who's there?"}
        {"Name": "Ed", "Text": "Go fmt."}
        {"Name": "Sam", "Text": "Go fmt who?"}
        {"Name": "Ed", "Text": "Go fmt yourself!"}
    `
    type Message struct {
        Name, Text string
    }
    dec := json.NewDecoder(strings.NewReader(jsonStream))
    for {
        var m Message
        if err := dec.Decode(&m); err == io.EOF {
            break
        } else if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("%s: %s\n", m.Name, m.Text)
    }
}

여기서 핵심은 OP가 디코딩을 찾고 있다는 것입니다.

type test_struct struct {
    Test string
}

...이 경우을 삭제 const jsonStream하고 Message구조체를 다음으로 대체 하십시오 test_struct.

func test(rw http.ResponseWriter, req *http.Request) {
    dec := json.NewDecoder(req.Body)
    for {
        var t test_struct
        if err := dec.Decode(&t); err == io.EOF {
            break
        } else if err != nil {
            log.Fatal(err)
        }
        log.Printf("%s\n", t.Test)
    }
}

업데이트 : 또한 이 게시물 은 JSON 응답에 대한 훌륭한 데이터를 제공한다고 덧붙였습니다. 저자는 struct tags내가 알지 못하는을 설명합니다 .

JSON은 일반적으로 보이지 {"Test": "test", "SomeKey": "SomeVal"}않지만 오히려 다음과 같이 {"test": "test", "somekey": "some value"}구조체를 재구성 할 수 있습니다.

type test_struct struct {
    Test string `json:"test"`
    SomeKey string `json:"some-key"`
}

... 이제 핸들러는 "SomeKey"(내부적으로 사용됨) 대신 "some-key"를 사용하여 JSON을 구문 분석합니다.

참고 URL : https://stackoverflow.com/questions/15672556/handling-json-post-request-in-go

반응형