
json null in golang
1 panic caused by null json
question: What will be printed when the code below is executed?
package main
import (
"encoding/json"
"fmt"
)
type person struct {
name string
age int
phone *string
}
func main() {
pJSON := []byte("null")
var p *person = nil
if err := json.Unmarshal(pJSON, &p); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(p.name)
}
A. Compile failed
B. Print nothing
C. failed to unmarshal, err: [omit the error]
D. panic: runtime error: invalid memory address or nil pointer derference [omit the stack information]
answer
D
analysis
null JSON in Golang will parsed as nil pointer, and the error will be nil.
code
p.name
will cause panic
2 JSON null
The following case will be encoded as null:
Array and slice values encode as JSON arrays, except that []byte encodes as a base64-encoded string, and a nil slice encodes as the null JSON value.
Pointer values encode as the value pointed to. A nil pointer encodes as the null JSON value.
Interface values encode as the value contained in the interface. A nil interface value encodes as the null JSON value.
The JSON null value unmarshals into an interface, map, pointer, or slice by setting that Go value to nil. Because null is often used in JSON to mean “not present,” unmarshaling a JSON null into any other Go type has no effect on the value and produces no error.
2.1 array and slice
2.1.1 Marshal
question: What will be printed when the code below is executed?
package main
import (
"encoding/json"
"fmt"
)
func main() {
var x []int
xJSON, err := json.Marshal(x)
if err != nil {
fmt.Println("failed to marshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(string(xJSON))
x = make([]int, 0, 0)
xxJSON, err := json.Marshal(x)
if err != nil {
fmt.Println("failed to marshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(string(xxJSON))
}
answer
true
null
false
[]
2.1.2 Unmarshal
question: What will be printed when the code below is executed?
package main
import (
"encoding/json"
"fmt"
)
func main() {
bs := []byte(`null`)
var x []int
fmt.Println(x == nil)
if err := json.Unmarshal(bs, &x); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(x)
bs = []byte(`[123,456]`)
var xx []int
fmt.Println(xx == nil)
if err := json.Unmarshal(bs, &xx); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(xx == nil)
fmt.Println(xx)
}
answer
true
true
[]
true
false
[123 456]
2.2 pointer example
2.2.1 Marshal
question: What will be printed when the code below is executed?
package main
import (
"encoding/json"
"fmt"
)
func main() {
var x *int
xJSON, err := json.Marshal(x)
if err != nil {
fmt.Println("failed to marshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(string(xJSON))
num := 110
x = &num
xxJSON, err := json.Marshal(x)
if err != nil {
fmt.Println("failed to marshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(string(xxJSON))
}
answer
true
null
false
110
2.2.2 Unmarshal
question: What will be printed when the code below is executed?
package main
import (
"encoding/json"
"fmt"
)
func main() {
bs := []byte(`null`)
var x *int
fmt.Println(x == nil)
if err := json.Unmarshal(bs, &x); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(x)
bs = []byte(`123`)
var xx *int
fmt.Println(xx == nil)
if err := json.Unmarshal(bs, &xx); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(xx == nil)
fmt.Println(xx, *xx)
}
answer
true
true
<nil>
true
false
0xc0000140a8 123
2.3 interface example
2.3.1 Marshal
question: What will be printed when the code below is executed?
package main
import (
"encoding/json"
"fmt"
)
func main() {
var x interface{}
xJSON, err := json.Marshal(x)
if err != nil {
fmt.Println("failed to marshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(string(xJSON))
x = 110
xxJSON, err := json.Marshal(x)
if err != nil {
fmt.Println("failed to marshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(string(xxJSON))
}
answer
true
null
false
119
2.3.2 Unmarshal
question: What will be printed when the code below is executed?
package main
import (
"encoding/json"
"fmt"
)
func main() {
bs := []byte(`null`)
var x interface{}
fmt.Println(x == nil)
if err := json.Unmarshal(bs, &x); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(x)
bs = []byte(`123`)
var xx interface{}
fmt.Println(xx == nil)
if err := json.Unmarshal(bs, &xx); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(xx == nil)
fmt.Println(xx)
}
answer
true
true
<nil>
true
false
123
2.4 map example
2.4.1 Marshal
question: What will be printed when the code below is executed?
package main
import (
"encoding/json"
"fmt"
)
func main() {
var x map[string]string
xJSON, err := json.Marshal(x)
if err != nil {
fmt.Println("failed to marshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(string(xJSON))
x = make(map[string]string)
xxJSON, err := json.Marshal(x)
if err != nil {
fmt.Println("failed to marshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(string(xxJSON))
}
answer
true
null
false
{}
2.4.2 Unmarshal
question: What will be printed when the code below is executed?
package main
import (
"encoding/json"
"fmt"
)
func main() {
bs := []byte(`null`)
var x map[string]string
fmt.Println(x == nil)
if err := json.Unmarshal(bs, &x); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(x)
bs = []byte(`{"abc":"123"}`)
var xx map[string]string
fmt.Println(xx == nil)
if err := json.Unmarshal(bs, &xx); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(xx == nil)
fmt.Println(xx)
}
answer
true
true
map[]
true
false
map[abc:123]
3 usage
3.1 example
question: What will be printed when the code below is executed?
package main
import (
"encoding/json"
"fmt"
)
type person struct {
name string
age int
friends []string
phone *string
}
func main() {
pJSON := []byte("null")
var p1 person
if err := json.Unmarshal(pJSON, &p1); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println("p1", p1, p1.phone == nil, p1.friends == nil)
var p2 *person = nil
if err := json.Unmarshal(pJSON, &p2); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println("p2", p2 == nil, p2)
}
answer
p1 { 0 [] <nil>} true true
p2 true <nil>
3.2 hint
null 是个特殊字符串,经过 json.Unmarshal 处理后,返回的 err 为 nil
p1 定义为 person 本身,null 解析后,person 所有成员字段均为 golang 默认值
p2 定义为 person 指针,null 解析后,p2 为 nil 指针
4 reference
https://golang.org/pkg/encoding/json/




