SupaHam
SupaHam

Reputation: 1225

JSON Apply mapping of a map to object

I'm writing a REST endpoint for an Update operation on a model. The mapping is simply a forwarding of the request's body as []byte to json.Unmarshal. However, I'm now trying to filter out the uuid property from being changed on said model. So instead of unmarshaling to the model I am now doing it to a map[string]interface{} and then running delete(m, "uuid").

At this point I have a map of the data, but how can I feed it into the json to map it as it usually would when calling Unmarshal or Decode? Is there a better option than marshaling for a []byte result and then unmarshal onto the model?

Upvotes: 2

Views: 583

Answers (1)

icza
icza

Reputation: 418565

You may mark the UUID field of your object (struct) with json:"-" so it will be excluded from the marshaling / unmarshaling process, e.g.:

type User struct {
    Name string `json:"name"`
    UUID string `json:"-"`
}

If you do need to marshal / unmarshal the UUID field too at other places of your app, then the simplest solution would be to store the UUID field before unmarshaling, then restore it after the marshaling, e.g.:

u := getUser() // acquire your object

uuid := u.UUID // save field

err := json.Unmarshal(data, &u)
// handle error

u.UUID = uuid // restore field

Wrap it in a utility function, so you can reuse it:

func decodeUser(u *User, data []byte) error {
    uuid := u.UUID // save field
    if err := json.Unmarshal(data, &u); err != nil {
        return err
    }
    u.UUID = uuid // restore field
    return nil
}

Note that there are 3rd party libs for mapping maps to struts values (e.g. github.com/mitchellh/mapstructure), but unmarshaling into a map first, then mapping that into a struct is significantly slower than to unmarshaling into the struct value and storing / restoring a single field.

Upvotes: 5

Related Questions