Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

Assume i have a struct like

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

Then in main i have code

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

apparently the code above produce a nil error, regardless the json format is different. When will json.Unmarshal() return error in Go?

like image 925
Wendy Adi Avatar asked Sep 22 '15 05:09

Wendy Adi


People also ask

How does JSON Unmarshal work?

To unmarshal a JSON array into a slice, Unmarshal resets the slice length to zero and then appends each element to the slice. As a special case, to unmarshal an empty JSON array into a slice, Unmarshal replaces the slice with a new empty slice.

What does Unmarshal JSON mean?

Go's terminology calls marshal the process of generating a JSON string from a data structure, and unmarshal the act of parsing JSON to a data structure.

How does Unmarshal work in Golang?

Golang Unmarshal Unmarshal is the contrary of marshal. It allows you to convert byte data into the original data structure. In go, unmarshaling is handled by the json. Unmarshal() method.

What is JSON marshal and Unmarshal in Golang?

In Golang, struct data is converted into JSON and JSON data to string with Marshal() and Unmarshal() method. The methods returned data in byte format and we need to change returned data into JSON or String. In our previous tutorial, we have explained about Parsing JSON Data in Golang.


2 Answers

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

like image 55
Bayta Darell Avatar answered Sep 20 '22 12:09

Bayta Darell


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"
like image 44
icza Avatar answered Sep 18 '22 12:09

icza