I am trying to concatenate two values, door and access, from a JSON object into a map[string]bool, which is declared inside a struct. Right now, I am getting the error:
json: cannot unmarshal string into Go struct field Data.pasted of type map[string]bool
The struct is defined as follows:
type AccessControl struct{
SessionId string `json:"sessionId"`
DoorAccess map[string]bool
}
The JSON object I am getting from the server is:
{
"sessionId": "232",
"door": "Main Door",
"access": true
}
And this is my function:
func handler(w http.ResponseWriter, r *http.Request){
var data AccessControl
err := json.NewDecoder(r.Body).Decode(&data)
}
your json and your struct are not representing the same object your struct should be as follows:
type AccessControl struct {
SessionID string `json:"sessionId"`
Door string `json:"door"`
Access bool `json:"access"`
}
and for the "full example" that you asked for:
type ServerAccessControl struct {
SessionID string `json:"sessionId"`
Door string `json:"door"`
Access bool `json:"access"`
}
type AccessControl struct {
SessionId string `json:"sessionId"`
DoorAccess map[string]bool
}
func main() {
jsn := `{ "sessionId": "232", "door": "Main Door", "access": true }`
var data ServerAccessControl
json.Unmarshal([]byte(jsn), &data)
accessControl := ServerAccessControlToAccessControl(&data)
fmt.Println(accessControl)
}
//ServerAccessControlToAccessControl convert a access control obj from the server into a map based struct.
func ServerAccessControlToAccessControl(fromServer *ServerAccessControl) AccessControl {
var accessControl AccessControl
accessControl.SessionId = fromServer.SessionID
accessControl.DoorAccess = make(map[string]bool)
accessControl.DoorAccess[fromServer.Door] = fromServer.Access
return accessControl
}
I created the ServerAccessControl struct which represent the json that you are getting from the server and the Access Control class as you wanted it.
It is important that you will notice that you are not getting a collection from the server, and if you plan to add more doors into your map, you will need to implement the logic your self.
Sounds like you want to use a custom Unmarshaller. Here's an example. See my comments for articles explaining the process.
package main
import (
"encoding/json"
"fmt"
"log"
)
var data = `{
"sessionId": "232",
"door": "Main Door",
"access": true
}`
type AccessControl struct {
SessionId string `json:"sessionId"`
DoorAccess map[string]bool
}
func (a *AccessControl) UnmarshalJSON(data []byte) error {
tmp := struct {
SessionID string `json:"sessionId"`
Door string `json:"door"`
Access bool `json:"access"`
}{}
err := json.Unmarshal(data, &tmp)
if err != nil {
return err
}
a.SessionId = tmp.SessionID
a.DoorAccess = map[string]bool{tmp.Door: tmp.Access}
return nil
}
func main() {
var ac AccessControl
err := json.Unmarshal([]byte(data), &ac)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v
", ac)
}