Basically I'm trying to implement set-only and view-only struct fields cleanly. I'm using a document store using JSON as the data format, which is why I'm trying to get encoding/json to do what I want.
I've come up with couple approaches:
Has anyone else run into a similar problem?
I have a struct like this:
type Account struct {
Username string
Password string
// lots of other fields
}
When a user creates an account, I need to get the password. This password is required for communicating with an external service (it doesn't support OAuth or anything like that) in the background on behalf of the user. These fields need to be saved in the database, but shouldn't be accessible through the API. I understand that this isn't a good security model, but that's beside the point.
I would like to just unmarshal into my struct on input (so users can update fields) and marshal my struct on output (so the user can see everything but hidden fields), however this does not seem to be possible.
I created issue 7337 to add (Un)MarshalTag (takes a variadic list of tags to consider), which was rejected on the grounds that it promotes an undesirable idiom. I understand the sentiment, and it doesn't seem likely to be reconsidered, so I'd like to discuss alternatives.
In my case, I have three different cases I need to account for:
- user input
- displaying data to the user
- storing data in the database
Basically I'm trying to implement set-only and view-only struct fields cleanly. I'm using a document store using JSON as the data format, which is why I'm trying to get encoding/json to do what I want.
I've come up with couple approaches:
- use tags and pass struct into a function that produces a map[string]interface{} recursively, which is then passed into json.Marshal
- Unmarshal will work in reverse (unmarshal into map[string]interface{}, recursively update a struct
- ignores the sentiment that this type of tag use abuses the feature
- is computationally more expensive because every (Un)Marshal has to do a reflection pass first
- have a struct definition for each interface (set API, DB, view API) that each implement (Un)MarshalJSON, and one master struct that gets updated
- adding or deleting a field requires changes in multiple places, potentially error prone
- adding a different serialization is more difficult and changes must be made in multiple places