Home > Software engineering >  Cannot Unmarshal JSON String to struct in Go
Cannot Unmarshal JSON String to struct in Go

Time:08-01

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.

CodePudding user response:

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":"[email protected]"
}

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)
}

CodePudding user response:

Use go tag like this:

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

CodePudding user response:

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.

  • Related