Go : When will json.Unmarshal to struct return error?

后端 未结 3 1430
时光说笑
时光说笑 2020-12-31 04:15

Assume i have a struct like

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

Then in main i have code

var jsonString string =          


        
相关标签:
3条回答
  • 2020-12-31 04:32

    To add to icza's answer, you can also get an error if you try to Unmarshal into a typed nil pointer. This can happen if, for example, you make a slice of pointers to a particular type, then try and unmarshal into a particular one of those pointers.

    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)
    
    0 讨论(0)
  • 2020-12-31 04:45

    The JSON decoder does not report an error if values in the source do not correspond to values in the target. For example, it's not an error if the source contains the field "status", but the target does not.

    The Unmarshal function does return errors in other situations.

    Syntax error

    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
    

    JSON value not representable by target type:

    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
    

    (This is one example of where the value cannot be represented by target type. There are more.)

    playground example

    0 讨论(0)
  • 2020-12-31 04:52

    And more examples when json.Unmarshal() returns an error (besides specifying an invalid JSON):

    Specifying a nil or empty slice:

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

    Specifying a non-pointer to unmarshal into:

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

    Specifying nil as the target pointer:

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

    Specifying JSON numbers that would overflow the target type. Quoting the doc of json.Unmarshal():

    If a JSON value is not appropriate for a given target type, or if a JSON number overflows the target type, Unmarshal skips that field and completes the unmarshalling as best it can. If no more serious errors are encountered, Unmarshal returns an UnmarshalTypeError describing the earliest such error.

    To demonstrate this:

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

    Or when trying to parse something as a time.Time which is not an RFC3339 timestamp:

    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"
    
    0 讨论(0)
提交回复
热议问题