web-dev-qa-db-ja.com

Go on Requestの本文からJSONを取得する方法

私はGoの初心者ですが、今のところとても気に入っています。

理解できない問題があります。私はNodeからGoにAPIを移行していて、POST現状のまま、Postgresqlデータベースのjsonbタイプの列に保存します。

つまり、structなどの事前に定義されたものは使用できません。

POSTは次のようにbody raw _Content-Type: application/json_で作成されます:

_{
    "debug": false,
    "order_id_gea": 326064,
    "increment_id_gea": 200436102,
    "date": "2017-05-18T01:44:44+00:00",
    "total_amount": 10000.00,
    "currency": "MXN",
    "payment_method": "Referencia bancaria",
    "reference": "857374",
    "buyer": {
        "buyer_id_gea": 1234,
        "full_name": "Juan Perez Martinez",
        "email": "[email protected]",
        "phone": "5512341234"
    },
    "products": [
        {
            "sku":"PEP16114",
            "price": 10000.00,
            "currency": "MXN",
            "student": {
                "school_id_gea": 172,
                "grade_id_gea": 119,
                "level_id_gea": 36,
                "name": "Benancio",
                "last_name": "Perez",
                "second_last_name": "Garcia",
                "email": "[email protected]"
            }
        }
    ]
}
_

Node + Hapiは非常に簡単です:

_const payload = request.payload
_

その後、payloadからJSONにアクセスできます。

私はGo with Echoを使用しているので、 contextRequest() *http.Requestを見つけることができるラッパーです。

私は以下を試しましたが、結果が空であるか、空であるためエラーが発生します:

_var v interface{}
err := json.NewDecoder(context.Request().Body).Decode(&v)
if err != nil {
    return result, err
}
fmt.Println(v)
_

結果:EOF

-

_m := echo.Map{}
if err := context.Bind(&m); err != nil {
    return result, err
}
fmt.Println(m)
_

結果コード400、メッセージEOF

-

_body, error := ioutil.ReadAll(context.Request().Body)
if error != nil {
    return result, error
}
fmt.Println(body)
_

結果[]

-

何が欠けているか、または間違っていますか?ありがとう!

6
transistor

TILは_http.Response.Body_がバッファであることを意味します。つまり、一度読み取られると、再度読み取ることはできません。

それは水の流れのようなもので、それを見てそれが通過するときにそれを測定することができますが、一度なくなるとそれは消えます。

ただし、これを知っていると、回避策があり、ボディを「キャッチ」して復元する必要があります。

_// Read the Body content
var bodyBytes []byte
if context.Request().Body != nil {
    bodyBytes, _ = ioutil.ReadAll(context.Request().Body)
}

// Restore the io.ReadCloser to its original state
context.Request().Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))

// Continue to use the Body, like Binding it to a struct:
order := new(models.GeaOrder)
error := context.Bind(order)
_

これで、どこかでcontext.Request().Bodyを使用できます。

出典:

http://grokbase.com/t/gg/golang-nuts/12adq8a2ys/go-nuts-re-reading-http-response-body-or-any-reader

https://medium.com/@xoen/golang-read-from-an-io-readwriter-without-loosing-its-content-2c6911805361

14
transistor