GoLang的Get方法返回缺失的信息。

huangapple go评论83阅读模式
英文:

GoLang Get Method Returns Missing Info

问题

我正在尝试使用golang、gin和gorm框架获取一些个人资料信息。这是我的数据结构:

type Model struct {
    Skills    []string
    Languages []string
}

这是我的方法:

var skillname []string
var languagename []string
var langs []Models.Language
var skills []Models.Skill

session, _ := store.Get(c.Request, "sessioncontrol")
i := session.Values["sessionid"]

skillcount := int(Config.DB.Find(&skills, "user_id = ?", i).RowsAffected)
langcount := int(Config.DB.Find(&langs, "user_id = ?", i).RowsAffected)

fmt.Println(langcount)
fmt.Println(skillcount)

for _, lang := range langs {
    var langc Models.LanguageCatalog
    
    fmt.Printf("lang:")
    fmt.Println(langcount)
    Config.DB.First(&langc, "id = ?", lang.LanguageCatalogID)
    
    fmt.Printf("catalogname:")
    fmt.Println(langc.Name)
    
    languagename = append(languagename, langc.Name)
}

for _, skill := range skills {
    var skillc Models.SkillCatalog
    
    fmt.Printf("skill:")
    fmt.Println(skillcount)
    Config.DB.First(&skillc, "id = ?", skill.SkillCatalogID)
    
    fmt.Printf("catalognames:")
    fmt.Println(skillc.Name)
    
    skillname = append(skillname, skillc.Name)
}

for _, snm := range skillname {
    fmt.Println(snm)
}
for _, lnm := range languagename {
    fmt.Println(lnm)
}

model.Skills = skillname
model.Languages = languagename

for _, skname := range model.Skills {
    fmt.Println(skname)
}
for _, lname := range model.Languages {
    fmt.Println(lname)
}

err := c.ShouldBindJSON(&model)
c.JSON(200, model)

fmt.Print(err)
return

我使用fmt方法来检查数据是否实际接收到了,而且确实接收到了。这是我的终端输出:

2
4
lang:2
catalogname:Spanish
lang:2
catalogname:German
skill:4
catalognames:Java
skill:4
catalognames:.net
skill:4
catalognames:JQuery
skill:4
catalognames:Go
Java
.net
JQuery
Go
Spanish
German
Java
.net
JQuery
Go
Spanish
German
json: cannot unmarshal object into Go struct field Model.Languages of type string

我确实有4个技能记录和2个语言方法,就像在终端和数据库中打印的那样。然而,当我使用Postman调用GET方法时,我得到的结果是:

{
  "Languages": [
    "Spanish"
  ],
  "Skills": [
    "Java",
    ".net"
  ]
}

由于我得到了"cannot unmarshal"错误,我尝试使用模型数组而不是字符串数组,但结果仍然相同,没有错误消息。为了通过GET调用获取完整数据,我应该怎么做?谢谢你的时间。

英文:

I am trying to get some profile info using golang, gin and gorm frame works. Here is my data struct.

type Model struct {
Skills         []string
Languages      []string
}

And my method;

	var skillname []string
var languagename []string
var langs []Models.Language
var skills []Models.Skill
session, _ := store.Get(c.Request, "sessioncontrol")
i := session.Values["sessionid"]
skillcount := int(Config.DB.Find(&skills, "user_id = ?", i).RowsAffected)
langcount := int(Config.DB.Find(&langs, "user_id = ?", i).RowsAffected)
fmt.Println(langcount)
fmt.Println(skillcount)
for _, lang := range langs {
var langc Models.LanguageCatalog
fmt.Printf("lang:")
fmt.Println(langcount)
Config.DB.First(&langc, "id = ?", lang.LanguageCatalogID)
fmt.Printf("catalogname:")
fmt.Println(langc.Name)
languagename = append(languagename, langc.Name)
}
for _, skill := range skills {
var skillc Models.SkillCatalog
fmt.Printf("skill:")
fmt.Println(skillcount)
Config.DB.First(&skillc, "id = ?", skill.SkillCatalogID)
fmt.Printf("catalognames:")
fmt.Println(skillc.Name)
skillname = append(skillname, skillc.Name)
}
for _, snm := range skillname {
fmt.Println(snm)
}
for _, lnm := range languagename {
fmt.Println(lnm)
}
model.Skills = skillname
model.Languages = languagename
for _, skname := range model.Skills {
fmt.Println(skname)
}
for _, lname := range model.Languages {
fmt.Println(lname)
}
err := c.ShouldBindJSON(&model)
c.JSON(200, model)
fmt.Print(err)
return

I used fmt methods to check whether data is actually receiving or not. And it is. Here is my terminal output;

2
4
lang:2
catalogname:Spanish
lang:2
catalogname:German
skill:4
catalognames:Java
skill:4
catalognames:.net
skill:4
catalognames:JQuery
skill:4
catalognames:Go
Java
.net
JQuery
Go
Spanish
German
Java
.net
JQuery
Go
Spanish
German
json: cannot unmarshal object into Go struct field Model.Languages of type string

I really have 4 skills record and 2 language method like printed in the terminal at the database. However when I call GET method using postman what I got is;

{
"Languages": [
"Spanish"
],
"Skills": [
"Java",
".net"
]
}

Since I got "cannot unmarshal" error, I tried same by using model arrays instead of string arrays but the result was same without the error message. What should I do in order to get full data by GET call. Thanks for your time.

答案1

得分: 1

我猜测你从Postman传入的请求包括一个请求体(例如 {"Skills":["Java",".net"],"Languages":["Spanish"]})。在这种情况下,我们可以使用以下代码复制该问题:

package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http/httptest"

	"github.com/gin-gonic/gin"
)

type Model struct {
	Skills    []string
	Languages []string
}

func main() {
	// 模拟一个HTTP请求(使我们能够提供一个最小化、可重现的示例)
	requestTxt := bytes.NewBuffer([]byte(`{"Skills":["Java",".net"],"Languages":["Spanish"]}`))
	req := httptest.NewRequest("GET", "/", requestTxt)
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = req

	// 填充切片(数据库查询与问题无关-你已经证明它们有效)
	skills := []string{"Java", ".net", "JQuery"}
	langs := []string{"Spanish", "German"}

	model := Model{
		Skills:    skills,
		Languages: langs,
	}

	// 根据你的问题编写代码
	err := c.ShouldBindJSON(&model)
	fmt.Println("ShouldBindJSON Error", err)

	c.JSON(200, model)

	// 输出将发送回Postman的响应
	body, _ := io.ReadAll(w.Result().Body)
	fmt.Println("response: ", string(body))
}

运行这段代码会得到你所说的结果:

{"Skills":["Java",".net"],"Languages":["Spanish"]}

之所以会出现这种情况,是因为context.ShouldBindJSON将请求解析为你传入的变量;它用于当你期望请求包含JSON并希望将其解组为Go的struct时。因此,你首先将数据放入model,然后通过调用ShouldBindJSON来覆盖它。

要修复这个问题,删除err := c.ShouldBindJSON(&model)这一行(以及打印错误的那一行),结果将如预期:

{"Skills":["Java",".net","JQuery"],"Languages":["Spanish","German"]}

注意:正如我在开始时所说,这是基于一些猜测。如果这没有帮助,请修改我提供的代码,使其与你的情况相匹配(如果你提供一个最小化、可重现的示例,那么理解和回答你的问题会更简单)。

英文:

I'm going to guess that the request you are passing in from postman includes a request body (e.g. {"Skills":["Java",".net"],"Languages":["Spanish"]}). That being the case we can duplicate the issue with:

package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http/httptest"

	"github.com/gin-gonic/gin"
)

type Model struct {
	Skills    []string
	Languages []string
}

func main() {
	// Simulate an HTTP request (enables us to provide a Minimal, Reproducible Example)
	requestTxt := bytes.NewBuffer([]byte(`{"Skills":["Java",".net"],"Languages":["Spanish"]}`))
	req := httptest.NewRequest("GET", "/", requestTxt)
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = req

	// Populate the slices (the database queries are irrelevant - you have shown that they work)
	skills := []string{"Java", ".net", "JQuery"}
	langs := []string{"Spanish", "German"}

	model := Model{
		Skills:    skills,
		Languages: langs,
	}

	// Code as per your question
	err := c.ShouldBindJSON(&model)
	fmt.Println("ShouldBindJSON Error", err)

	c.JSON(200, model)

	// Output the response that would be sent back to postman
	body, _ := io.ReadAll(w.Result().Body)
	fmt.Println("response: ", string(body))
}

Running this gives me the result you say you are getting:

{"Skills":["Java",".net"],"Languages":["Spanish"]}

The reason that this is happening is that context.ShouldBindJSON process the request INTO the variable you pass; it is used when you expect the request to contain JSON and want to unmarshal that into a Go struct. So you are putting data into model and then overwriting it with the call to ShouldBindJSON.

To fix this remove the line err := c.ShouldBindJSON(&model) (and the line printing the error) and the result will be as expected:

{"Skills":["Java",".net","JQuery"],"Languages":["Spanish","German"]}

Note: As I said at the start this is based on some guesswork. If this does not help please modify the code I have provided so that it matches your situation (if you provide a minimal, reproducible example then it's a lot simpler to understand/answer your question).

huangapple
  • 本文由 发表于 2022年8月6日 20:37:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/73259800.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定