暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

json null in Golang

百里分麾 2021-06-21
6046

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/


文章转载自百里分麾,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论