无法将 JSON 字符串解组为 Go 中的结构体。

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

Cannot Unmarshal JSON String to struct in Go

问题

我有一个字符串,它是一个Go模块中的HTTP响应体。它看起来像这样:

bodyString = `{"firstname": "foo", "lastname": "bar", "username": "foobar"}`

我想将其转换为以下的Go结构体:

type Params struct {
  FirstName string
  LastName string
  Username string
  PasswordHash string 
  EmailAddress string
}

我尝试使用以下代码来实现:

var jsonMap map[string]interface{}
json.Unmarshal([]byte(bodyString), &jsonMap)

paramsIn.FirstName = jsonMap["firstname"].(string)
paramsIn.LastName = jsonMap["lastname"].(string)
paramsIn.Username = jsonMap["username"].(string)
paramsIn.PasswordHash = jsonMap["passwordhash"].(string)
paramsIn.EmailAddress = jsonMap["emailaddress"].(string)

然而,解析失败,无法将字符串中的数据与相应的键匹配。也就是说,jsonMap变量中只有空字符串。

显然,我做错了什么,我在Go中没有太多处理json的经验。如果有人能帮助我或者展示正确的从字符串解析json数据的方法,那就太好了,谢谢。

英文:

I have a string in my Go module which is the body of a HTTP response. it looks something like this:

bodyString = `{"firstname": "foo", "lastname": "bar", "username": "foobar"}`

I want to convert it to the following Go struct:

type Params struct {
  FirstName string
  LastName string
  Username string
  PasswordHash string 
  EmailAddress string
}

I attempt to do so using the following:

var jsonMap map[string]interface{}
json.Unmarshal([]byte(bodyString), &jsonMap)

paramsIn.FirstName = jsonMap["firstname"].(string)
paramsIn.LastName = jsonMap["lastname"].(string)
paramsIn.Username = jsonMap["username"].(string)
paramsIn.PasswordHash = jsonMap["passwordhash"].(string)
paramsIn.EmailAddress = jsonMap["emailaddress"].(string)

However the unmarshal fails to match the data in the string to the appropriate keys. i.e. what is stored in the jsonMap variable is only empty strings.

I clearly am doing something wrong and I haven't worked with json in Go very much. If any one can help or show me the correct way to unmarshal json data from a string that would be great, thanks.

答案1

得分: 2

Golang会将你的结构体字段名(CammelCase)转换为snake_case(默认)。所以,如果你有以下结构体:

type Params struct {
  FirstName string
  LastName string
  Username string
  PasswordHash string 
  EmailAddress string
}

该结构体的JSON将会是:

{
    "first_name":"bla",
    "last_name":"bla",
    "user_name":"bla",
    "password_hash":"ewedsads",
    "email_address":"bla@gmail.com"
}

但是你可以通过使用json标签来自定义JSON字段名,例如:

type Params struct {
  FirstName string `json:"firstname"`
  LastName string `json:"lastname"`
  Username string `json:"username"`
  PasswordHash string `json:"passwordhash"`
  EmailAddress string `json:"emailaddress"`
}

然后你可以像这样修改你的代码:

package main

import (
	"encoding/json"
	"fmt"
)

type Params struct {
	FirstName    string `json:"firstname"`
	LastName     string `json:"lastname"`
	Username     string `json:"username"`
	PasswordHash string `json:"passwordhash"`
	EmailAddress string `json:"emailaddress"`
}

func main() {
	paramsIn := Params{}
	bodyString := `{"firstname": "foo", "lastname": "bar", "username": "foobar"}`

	json.Unmarshal([]byte(bodyString), &paramsIn)
	fmt.Println(paramsIn)
}
英文:

Golang will convert your struct's field name (CammelCase) to snake_case (default). So, if you have struct like :

type Params struct {
  FirstName string
  LastName string
  Username string
  PasswordHash string 
  EmailAddress string
}

The JSON from the struct will be :

{
    "first_name":"bla",
    "last_name":"bla",
    "user_name":"bla",
    "password_hash":"ewedsads",
    "email_address":"bla@gmail.com"
}

But you can customize the JSON field name by json tag, example :

type Params struct {
  FirstName string `json:"firstname"`
  LastName string `json:"lastname"`
  Username string `json:"username"`
  PasswordHash string `json:"passwordhash"`
  EmailAddress string `json:"emailaddress"`
}

Then you can change your code like this :

package main

import (
	"encoding/json"
	"fmt"
)

type Params struct {
	FirstName    string `json:"firstname"`
	LastName     string `json:"lastname"`
	Username     string `json:"username"`
	PasswordHash string `json:"passwordhash"`
	EmailAddress string `json:"emailaddress"`
}

func main() {
	paramsIn := Params{}
	bodyString := `{"firstname": "foo", "lastname": "bar", "username": "foobar"}`

	json.Unmarshal([]byte(bodyString), &paramsIn)
	fmt.Println(paramsIn)
}

答案2

得分: 0

使用go标签的示例:

type Params struct {
    FirstName    string `json:"firstname"`
    LastName     string `json:"lastname"`
    Username     string `json:"username"`
    PasswordHash string
    EmailAddress string
}

在上述示例中,Params结构体的字段使用了go标签。标签是用于给字段添加元数据的特殊注释,可以在运行时通过反射来获取。在这个例子中,字段FirstNameLastNameUsername都添加了json标签,用于指定在JSON序列化和反序列化时字段的名称。例如,FirstName字段在JSON中的名称将被指定为"firstname"PasswordHashEmailAddress字段没有添加标签,因此它们在JSON序列化和反序列化时将使用字段的原始名称。

英文:

Use go tag like this:

    type Params struct {
        FirstName    string `json:"firstname"`
        LastName     string `json:"lastname"`
        Username     string `json:"username"`
        PasswordHash string
        EmailAddress string
    }

答案3

得分: 0

这可能不是适用于每个遇到这个问题的人的解决方案,你应该查看本帖和其他类似的SO帖子上的其他答案。

对我来说,问题出在双引号字符的处理上(")。我的JSON字符串是从HTTP响应的主体中创建的,该响应是由另一个终端窗口中的curl命令提供的。我在MacOS的标准文本编辑器中编写了我的curl命令,但是我使用的是RTF(富文本格式),它将我的"字符格式化为其他字符()(虽然差异微小,但足以让我完全困惑了几个小时!)。一旦我在HTTP请求主体中使用了正确的双引号字符,上面的代码就没有问题。

如果我表达不清楚,请留言,我可以提供更多解释。

英文:

This may not be the solution to everyone who is experience this problem, and you should check out the other answers on this post and other similar SO posts.

For me the issue was how the double quote character was being treated ("). My json string was being created from the body of a http response, which was being fed by a curl command in another terminal window. I was writing my curl commands in MacOS's standard text editor but I was in RTF (Rich Text Format) which formatted my " character as something else () (The difference is miniscule but it was enough to completely stump me for hours!). There is no issue with the code above once I used the proper double quote character in the http request body.

If I am unclear, please comment and I can clarify more.

huangapple
  • 本文由 发表于 2022年8月1日 14:09:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/73189428.html
匿名

发表评论

匿名网友

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

确定