2017-10-05 3 views
-1

何らかの理由で要求が失敗した場合、サーバーが常にjsonエラーオブジェクトで応答するケースがあります。サーバーは常にHTTP 200で応答します。したがって、トークンが期限切れになり、例えば:代わりに、私は私が非整列化のためinterface{}を取る機能を持っている{"error":401, "msg":"Unauthorized"}不正なJSONが構造体にエラーなしで固定されています

を提供しています {"FirstName": "Bob", "LastName": "Smith"} を取得

type Person struct { FirstName string LastName string }

実施例にそれを置く
func (ah *APIHandler) getObjectFromJson(bodyResponse string, target interface{}) *ServerError { 
    parsingError := json.NewDecoder(strings.NewReader(bodyResponse)).Decode(target) 
    // when server responds with ServerError I expect to get persingError here and proceed to unmarshalling the error message 
    if parsingError != nil { 
     fmt.Println(parsingError.Error()) 
     var err *ServerError = &ServerError{} 
     parsingError = json.NewDecoder(strings.NewReader(bodyResponse)).Decode(err) 
     if parsingError != nil { 
      // this means unmarshalling ServerError failed 
      panic(parsingError.Error()) 
     } 
     return err 
    } 
    return nil 
} 

、私は渡されたinterface{}に間違ったJSONを提供するとき、私は、コンソールにエラーが出ることを期待する「JSONは構造体と一致していない」ではなく、空の構造体。それは可能ですか?

私は50以上のモデルを持っていますので、フィールドの整列が正しく行われているかどうかをチェックするためにアンマーシャラーを書くのは避けたいと思います。それら。

https://play.golang.org/p/vecLomIXeB

+0

あなたがモデルを埋め込むかunmarshallersを書き込むことができない場合、あなたは常に 'インターフェースにデコードすることができます{}'マップ:https://play.golang.org/p/ewks8sHz99。しかし、最高の解決策ではありません。 – abhink

+0

@abhinkはい、私は+50モデル、合計+600フィールドで、手動ではできません。 – agilob

+0

脇に: '* ServerError'が' error'を実装している場合は、関数の署名を 'error'を返すように変更してください。 https://golang.org/doc/faq#nil_error – Peter

答えて

4

デコードする際の標準ライブラリには、常にマップされていないフィールドを無視します。これはそうでなければ、これらのモデルのすべてのコンシューマーを壊すことなくモデルに新しいフィールドを追加することができないためです。

認識されないフィールドをチェックする代わりに、レスポンスに2つのマーシャルをアンマーシャルするか、または期待どおりのデータに加えてエラーフィールドを解析してエラーフィールドが含まれているかどうかを確認します。あなたはすでにこれをしていますが、あなたはそれを逆にしています。

func (ah *APIHandler) getObjectFromJson(bodyResponse string, target interface{}) *ServerError { 
    b := []byte(bodyResponse) 

    se := &ServerError{} 
    if err := json.Unmarshal(b, &se); err != nil { 
      // ... 
    } 
    if se.Error != "" { 
      return se 
    } 

    if err := json.Unmarshal(b, target); err != nil { 
      // ... 
    } 

    return nil 
} 
+0

を参照してください。ターゲットのマップを作成してマップを構造体に変換するよりも良いアイデアは、 'ServerError'は常に同じですが' target 'ではない。 – agilob

関連する問題