2016-11-22 2 views
0

少し前に、json.UnmarshalTypeErrorタイプにOffsetの値を追加しました(コンテキストについては、閉鎖された問題hereを参照)。オフセット値の背後にある目的は意味がありますが、タイプhttp:// io.ReadCloserのgo http応答本文を読み込むときにどのように使用できるかはわかりません。例えばより良いエラー処理のために、enconding/jsonのUnmarshalTypeErrorでオフセット値を使用するにはどうすればよいですか?

// An UnmarshalTypeError describes a JSON value that was 
// not appropriate for a value of a specific Go type. 
type UnmarshalTypeError struct { 
    Value string  // description of JSON value - "bool", "array", "number -5" 
    Type reflect.Type // type of Go value it could not be assigned to 
    Offset int64  // error occurred after reading Offset bytes 
} 

:捕まるエラーの時点で

var body CustomType 
decoderErr := json.NewDecoder(response.Body).Decode(&body) 

if decoderErr != nil { 

    if typeError, ok := decoderErr.(*json.UnmarshalTypeError); ok { 
     // Do something with typeError.Offset here 
    } 


} 

、私はすでにjson.NewDecoder...経由response.Bodyから読みました。私はもう一度response.Bodyを読む方法を探していますが、エラーのポイントまでは、typeErrorのOffset値を使用してください。

+0

が少しでもよくするつもりされていないエラーの時点まで読んで、あなただけの予期しないEOFエラーで非整列化エラーを交換しています。 – JimB

+0

最終的には、非マーシャリング時に問題の原因となったキーを取得するためにオフセットを使用したいと思いますが、response.Bodyを読み取ることができるのはステップ1です。 – Alex

+0

これで、repsonseボディをバッファリングする方法を尋ねていますか? – JimB

答えて

2

ボディを非整列化する前にボディを読み込んで保存する必要があるため、JSON構文またはタイプエラーがある場合は、以前に保存したボディを使用してより有用なエラーを返すことができます。コンセプトの

証明:

package main 

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

type Hello struct { 
    Name string `json:"name"` 
    Message string `json:"message"` 
} 

func main() { 
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 
     b, err := ioutil.ReadAll(r.Body) 
     if err != nil { 
      http.Error(w, "Error reading body", 400) 
      return 
     } 

     h := &Hello{} 
     if err := json.Unmarshal(b, &h); err != nil { 
      var msg string 
      switch t := err.(type) { 
      case *json.SyntaxError: 
       jsn := string(b[0:t.Offset]) 
       jsn += "<--(Invalid Character)" 
       msg = fmt.Sprintf("Invalid character at offset %v\n %s", t.Offset, jsn) 
      case *json.UnmarshalTypeError: 
       jsn := string(b[0:t.Offset]) 
       jsn += "<--(Invalid Type)" 
       msg = fmt.Sprintf("Invalid value at offset %v\n %s", t.Offset, jsn) 
      default: 
       msg = err.Error() 
      } 
      http.Error(w, msg, 400) 
      return 
     } 

     w.Write([]byte(`Good to go!`)) 
    }) 

    if err := http.ListenAndServe(":8000", nil); err != nil { 
     log.Fatal(err) 
    } 
} 
+0

これは素晴らしいです。私の例では 'json.NewDecoder(response.Body).Decode(&body)'を使用しましたが、ここでは 'json.Unmarshal'を使用します。以前の読書(http://stackoverflow.com/a/21198571/1569757)に基づいて、 'json.Decoder'を使う方が良いです。 json.Decoderでバイト配列を抽出することもできますか? – Alex

+0

@Alex - No. 'json.Decoder'を使用すると、割り当てを最小限に抑えることができますが、同じ効率でレスポンス本体を再度使用できなくなる場合には有益です。 – jmaloney

+0

それは意味があります。承認済みと表示されます。あなたはスーパーに役立ってきました。ありがとう! – Alex

関連する問題