web-dev-qa-db-ja.com

Go:json.Unmarshalが構造体を返すエラーはいつ発生しますか?

私のような構造を持っていると仮定します

type A struct{
  name string`json:"name"`
}

次に、メインにコードがあります

var jsonString string = `{"status":false}`
var a A
error := json.Unmarshal([]byte(jsonString),&a)

上記のコードは、json形式が異なっていても、明らかにnilエラーを生成します。 json.Unmarshal()はいつGoでエラーを返しますか?

13
Wendy Adi

ソースの値がターゲットの値に対応していない場合、JSONデコーダーはエラーを報告しません。たとえば、ソースに「ステータス」フィールドが含まれていても、ターゲットには含まれていなくてもエラーではありません。

Unmarshal関数は、他の状況ではエラーを返します。

構文エラー

type A struct {
    Name string `json:"name"`
}
data = []byte(`{"name":what?}`)
err = json.Unmarshal(data, &a)
fmt.Println(err)  // prints character 'w' looking for beginning of value

型の不一致

data := []byte(`{"name":false}`)
type B struct {
  Name string `json:"name"`
}
var b B
err = json.Unmarshal(data, &b)
fmt.Println(err) // prints cannot unmarshal bool into Go value of type string

遊び場の例

20
Cerise Limón

json.Unmarshal()がエラーを返す場合のその他の例(無効なJSONを指定する以外に):

nilまたはemptyスライスの指定:

_i := 0
err := json.Unmarshal(nil, &i)
fmt.Println(err) // unexpected end of JSON input
_

非マーシャリングする非ポインターの指定:

_err = json.Unmarshal([]byte(`{"name":"a"}`), i)
fmt.Println(err) // json: Unmarshal(non-pointer int)
_

ターゲットポインターとしてnilを指定:

_err = json.Unmarshal([]byte(`{"name":"a"}`), nil)
fmt.Println(err) // json: Unmarshal(nil)
_

ターゲットタイプをオーバーフローするJSON番号を指定します。 json.Unmarshal() のドキュメントを引用:

JSON値が特定のターゲットタイプに適切でない場合、またはJSON番号がターゲットタイプをオーバーフローする場合、Unmarshalはそのフィールドをスキップし、アンマーシャリングを可能な限り完了します。深刻なエラーが発生しなくなった場合、Unmarshalは、そのような最も早いエラーを説明するUnmarshalTypeErrorを返します。

これを実証するには:

_var j int8
err = json.Unmarshal([]byte(`1112`), &j)
fmt.Println(err) // json: cannot unmarshal number 1112 into Go value of type int8
_

または、RFC3339タイムスタンプではない_time.Time_として何かを解析しようとした場合:

_var t time.Time
err = json.Unmarshal([]byte(`"xx"`), &t)
fmt.Println(err) // parsing time ""xx"" as ""2006-01-02T15:04:05Z07:00"": cannot parse "xx"" as "2006"
_
8
icza

Iczaの答えに追加するために、型指定されたnilポインターに非整列化しようとすると、エラーが発生することもあります。これは、たとえば、特定の型へのポインターのスライスを作成し、それらのポインターの特定の1つにアンマーシャリングしようとした場合に発生する可能性があります。

package main

import (
    "fmt"
    "encoding/json"
)

type Example struct {Name string}


func main() {
        exs := make([]*Example, 5)
        err := json.Unmarshal([]byte(`{"name":"jane"}`), exs[0])
        fmt.Println(err)
}
// json: Unmarshal(nil *main.Example)
2
Czeslaw