2016-08-20 24 views
1

私はJSONとの間でリクエストとレスポンスの型をエンコード/デコードする関数を指定する必要があるライブラリ(go-kit)を使用しています。エンコードするには、単純です:Golang jsonのデコードでインタフェース{}のデコードに失敗しました

func EncodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error { 
    return json.NewEncoder(w).Encode(response) 
} 

HTTPサーバーを作成するためにこの関数を渡しても問題ありません。私のアプリケーション内のすべての単一のRPCについて

func decodeUppercaseRequest(_ context.Context, r *http.Request) (interface{}, error) { 
    var req UppercaseRequest 
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil { 
     return nil, err 
    } 
    return req, nil 
} 

:しかし、要求のための彼らの提案されたアプローチは、フォームの別の関数を作ることです。コードをDRYにして、何百ものほとんど同じメソッドを使用しないようにしたいと思っています。 、私はそう、JSONを不幸に

DecodeRequest(UppercaseRequest{}} 

func DecodeRequest(req interface{}) httptransport.DecodeRequestFunc { 
    return func(_ context.Context, r *http.Request) (interface{}, error) { 
     if err := json.NewDecoder(r.Body).Decode(&req); err != nil { 
      return nil, err 
     } 
     return req, nil 
    } 
} 

この関数は、そのように呼び出すことができます。そのため、私は与えられた要求の種類をデコードクロージャを生成する機能を書き込もうとしましたreqのタイプが実際にはmypackage.UppercaseRequestであっても、デコードは失敗します。私はここからどこに行くべきか分からない。リクエストタイプごとにメソッドを記述する必要がない方法がありますか?デコード関数がこの型が実行時に何であるかを理解するために何らかの方法がありますか?前もって感謝します!

ここ

は、問題を実証行く遊び場です: https://play.golang.org/p/GgHsLffp1G

+0

JSONデコードerrrorは何ですか?タイプスイッチが役立つかもしれませんし、パッケージにはランタイムタイプの識別のための多くのツールがあります。 – Sridhar

+0

@Sridhar私が呼び出す場合DecodeRequest(CountRequest {})私は 得る "HTTP:パニックサービング[:: 1]:55992:インタフェース変換:インタフェースはマップ[ストリング]インターフェース{}、ないuser.CountRequest" と私が使用する関数を変更すると... Decode(req)とDecodeRequest(&CountRequest {})を呼び出す "http:panic serving [:: 1]:56375:インターフェイス変換:インターフェイスは* user.CountRequestではないuser.CountRequest " –

+0

CountRequestとは何ですか?マップ[文字列]インターフェース{}?あなたは本当に[this](http://www.stackoverflow.com/help/mcve)に従うべきです。おそらくDecode(Req)を試してDecodeRequest(CountRequest {})を呼び出すでしょうか? – Sridhar

答えて

2

あなたは私たちを見せているコードの一部によると、私はあなたが型アサーションの問題に直面していると思います。私はplayground to show you what I explain belowを作成しました。

UpperCaseRequestをDecodeRequest関数に渡しています。この関数では、引数はinterface {}型であり、この引数のポインタをjsonデコーダに渡します。したがって、デコーダはUpperCaseRequestへのポインタではなく、インタフェースへのポインタを認識します。

これが正しくデコードされない理由です。そして、2つの異なる型を宣言することができないので、型宣言を試みることはできません。

だから、あなたのコードでは、私がお勧めしたい:

func DecodeRequest(req interface{}) httptransport.DecodeRequestFunc { 
    return func(_ context.Context, r *http.Request) (interface{}, error) { 
     // Note the '&' is removed here 
     if err := json.NewDecoder(r.Body).Decode(req); err != nil { 
      return nil, err 
     } 
     return req, nil 
    } 
} 

をそして、このように、この関数を呼び出します。

// Note the & is placed here. 
DecodeRequest(&UppercaseRequest{}} 
+0

残念ながら、これは私にとっては役に立ちません。私が試してみると、私が得るエラーは: http:panic serving [:: 1]:58709:インターフェース変換:インターフェースはuser.UppercaseRequestで、user.UppercaseRequestではありません。 –

+0

ああ!私はアイデアを持っていると思う - 多分問題は、jsonデコーダではなく、むしろ私は実際の構造体の代わりにポインタを返すよ。私は* req、nilを返す必要があると思う。しかし、私はどのようにインターフェイスへのポインタにインターフェイスをキャストできますか? –

+0

残念ながらどちらもうまくいきませんでした。問題を再現した私が追加した遊び場を確認してください。 –

関連する問題