Golang中如何处理内部结构体包含数据或null的情况

Golang中如何处理内部结构体包含数据或null的情况 我有这段代码:

type employee struct {          
    Id              string        `json:"id"`  
    Name              string        `json:"name"`  	
    Skills            struct {
        Id         int    `json:"id"`
        Name         int    `json:"name"`
    } `json:"desc"`
}

var bearer = xxxxxxxx
tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}  
req, _ := http.NewRequest("GET", url, nil)    
req.Header.Set("Authorization", fmt.Sprintf("%v", bearer))  
req.Close = false
res, err := tr.RoundTrip(req)
if err != nil {
	log.Println(err)
	return "error"
}
body, e := io.ReadAll(res.Body)  
if e != nil {
	log.Println(e)
	return "error"
}
var t skills
ers := json.Unmarshal([]byte(string(body)), &t) 
if ers != nil {
	log.Println(ers)
}

下面的数据示例没有错误:

{
 "Id": "01",
 "Name": "John",
 "Skills": {
    "Id": "01",
	"Name": "Developer"
 } 
}

但下面的另一个数据示例会因为 Skills 字段为 null 而出现错误:

{
 "Id": "01",
 "Name": "John",
 "Skills": null
}

这是错误日志:

2024/05/01 18:58:29 http: panic serving 10.x.x.x:60426: runtime error: index out of range [2] with length 1
goroutine 6 [running]:
net/http.(*conn).serve.func1()
	/usr/lib/golang/src/net/http/server.go:1854 +0xbf
panic({0x797720, 0xc0000c40d8})
	/usr/lib/golang/src/runtime/panic.go:890 +0x263
main.endpointHandler({0xc00008d998?, 0xe?}, 0xc00014a000, {0xe?, 0x7b9dc2?, 0xc00008d9e8?})
	/builds/devops/pipeline/gitops-notification/src_repo/cmd/webhookrl/webhookrl.go:225 +0xb08
main.rateLimiter.func1({0x84af80, 0xc000150000}, 0xc00014a000, {0xc00008da80?, 0xc00008db70?, 0x6c7c25?})
	/builds/devops/pipeline/gitops-notification/src_repo/cmd/webhookrl/webhookrl.go:263 +0xb6
github.com/julienschmidt/httprouter.(*Router).ServeHTTP(0xc000132000, {0x84af80, 0xc000150000}, 0xc00014a000)
	/builds/devops/pipeline/gitops-notification/src_repo/vendor/github.com/julienschmidt/httprouter/router.go:474 +0x1f7
net/http.serverHandler.ServeHTTP({0x849f30?}, {0x84af80, 0xc000150000}, 0xc00014a000)
	/usr/lib/golang/src/net/http/server.go:2936 +0x316
net/http.(*conn).serve(0xc000146000, {0x84b1a8, 0xc00007cde0})
	/usr/lib/golang/src/net/http/server.go:1995 +0x612
created by net/http.(*Server).Serve
	/usr/lib/golang/src/net/http/server.go:3089 +0x5ed
.
.
.

如果我像这样更改 JSON 结构体:

type skills struct {          
    Id              string        `json:"id"`  
    Name              string        `json:"name"`  	
    Skills            []interface{} `json:"skills"`     
}

我会得到这个错误:

json: cannot unmarshal object into Go struct field employee.skills of type []interface {}
http: panic serving 10.x.x.x:45812: runtime error: index out of range [2] with length 1
goroutine 18 [running]:

我不确定这是否是我需要放置的正确类型:

             []interface{}

这仅在我的其他代码中有效,如果它是数组而不是另一个结构体。

谢谢!


更多关于Golang中如何处理内部结构体包含数据或null的情况的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

嗯,我不明白为什么你在 Skills 字段里有 json:"desc",以及 var t skills 在那里是做什么的,但我假设这是一个打字错误。不过,我认为你错误的根本原因与你的 JSON 序列化或结构体定义无关。问题可能出在你代码的其他地方。

更多关于Golang中如何处理内部结构体包含数据或null的情况的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我检查了之前的JSON,这是我目前的结构:

type employee struct {          
    Id              string        `json:"id"`  
    Name              string        `json:"name"`  	
    Skills            struct {
        Id         int    `json:"id"`
        Name         int    `json:"name"`
    } `json:"desc"`
} `json:"unknown,omitempty"`

在Go中处理JSON中可能为null的内部结构体时,需要使用指针类型。当字段为null时,指针会被设置为nil,而不是引发解码错误。

以下是修改后的代码:

type employee struct {          
    Id     string `json:"id"`  
    Name   string `json:"name"`  	
    Skills *struct {
        Id   int `json:"id"`
        Name int `json:"name"`
    } `json:"skills"`
}

// 或者更清晰的写法:
type Skill struct {
    Id   int `json:"id"`
    Name int `json:"name"`
}

type employee struct {          
    Id     string `json:"id"`  
    Name   string `json:"name"`  	
    Skills *Skill `json:"skills"`
}

// 解码JSON
var emp employee
err := json.Unmarshal([]byte(jsonData), &emp)
if err != nil {
    log.Println(err)
    return
}

// 使用前检查Skills是否为nil
if emp.Skills != nil {
    fmt.Printf("Skill ID: %d\n", emp.Skills.Id)
    fmt.Printf("Skill Name: %d\n", emp.Skills.Name)
} else {
    fmt.Println("Skills is null")
}

对于你的具体代码,修改如下:

type employee struct {          
    Id     string `json:"id"`  
    Name   string `json:"name"`  	
    Skills *struct {
        Id   int `json:"id"`
        Name int `json:"name"`
    } `json:"skills"`
}

// 在解码部分
var t employee
err := json.Unmarshal(body, &t)
if err != nil {
    log.Println(err)
    return "error"
}

// 安全访问Skills字段
if t.Skills != nil {
    // 处理Skills数据
    fmt.Printf("Skill ID: %d\n", t.Skills.Id)
} else {
    // Skills为null的情况
    fmt.Println("No skills data available")
}

这样修改后,当JSON中的Skills字段为null时,t.Skills会是nil指针,而不会引发panic。你需要在访问Skills字段前检查它是否为nil。

回到顶部