繁体   English   中英

Go : json.Unmarshal 什么时候会返回 struct 错误?

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

假设我有一个像

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

然后在主要我有代码

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

显然上面的代码会产生一个 nil 错误,不管 json 格式是不同的。 json.Unmarshal() 什么时候会在 Go 中返回错误?

如果源中的值与目标中的值不对应,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

目标类型无法表示的 JSON 值:

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

(这是一个不能用目标类型表示值的例子。还有更多。)

游乐场示例

还有更多json.Unmarshal()返回错误的示例(除了指定无效的 JSON):

指定nilempty切片:

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

或试图解析的东西作为一个当time.Time这不是RFC3339时间戳:

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"

要添加到 icza 的答案中,如果您尝试将 Unmarshal 解组为类型化的 nil 指针,您也可能会收到错误消息。 例如,如果您创建一个指向特定类型的指针切片,然后尝试解组为这些指针中的特定一个,则可能会发生这种情况。

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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM