Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Custom unmarshalling from flat json to nested struct

Lets say I have two struct that are related like this:

type SecretUser struct {
    UserInfo `json:"userInfo"`
    Password string `json:"password"`
}

type UserInfo struct {
    FirstName string `json:"firstName"`
    LastName  string `json:"lastName"`
    Email     string `json:"email"`
}

And I receive a JSON in this form:

{
    "firstName": "nice",
    "lastName":"guy",
    "email":"nice@guy.co.uk",
    "password":"abc123"
}

I want to unmarshall this JSON into a SecretUser. Is there a better way than doing it like this?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

func (u *User) UnmarshalJSON(data []byte) error {
    var objmap map[string]*json.RawMessage
    var password string
    var err error

    err = json.Unmarshal(data, &objmap)
    if err != nil {
        return err
    }

    if err := json.Unmarshal(data, &u.UserInfo); err != nil {
        return err
    }
    
    err = json.Unmarshal(*objmap["password"], &password)
    if err != nil {
        return err
    }

    u.Password = password
    return nil
}

Basically, I partially unmarshall the JSON into a UserInfo struct and then read it again to extract the password. I don’t want to create another struct for just unmarshalling this JSON cleanly or use an external library (unless it’s part of the standard). Is there a more clean/efficient way of doing this, without reading the JSON twice or setting every field manually from a map?

>Solution :

Simply include the UserData into the SecretUser struct and do not specify a json tag for it.

type UserInfo struct {
    FirstName string `json:"firstName"`
    LastName  string `json:"lastName"`
    Email     string `json:"email"`
}

type SecretUser struct {
    UserInfo
    Password string `json:"password"`
}

func main() {
    data := []byte(`{"firstName": "nice","lastName":"guy","email":"nice@guy.co.uk","password":"abc123"}`)
    var u SecretUser
    _ := json.Unmarshal(data, &u)
    fmt.Println(u)
}

Go Play Space example

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading