Created
November 12, 2020 06:21
-
-
Save rohanthewiz/d4ca16baa5099506370f23a1418f73d8 to your computer and use it in GitHub Desktop.
JSON Marshal based on custom struct tags
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/json" | |
"fmt" | |
"reflect" | |
) | |
type User struct { | |
Username string `json:"user" db:"username"` | |
DisplayName string `json:"displayName" db:"display_name"` | |
Email string `json:"email"` | |
} | |
// - Unmarshalled from UI <-- {"user": "user123", "displayName": "John Brown","email": "[email protected]"} | |
// - Marshalled for DB --> {"username":"user123","display_name":"John Brown","email":"[email protected]"} | |
func main() { | |
var user User | |
const userAsString = `{"user": "user123", "displayName": "John Brown","email": "[email protected]"}` | |
err := json.Unmarshal([]byte(userAsString), &user) | |
if err != nil { | |
fmt.Println(err) | |
} | |
jsonByte, err := json.Marshal(&user) | |
if err != nil { | |
fmt.Println(err) | |
} | |
fmt.Println(string(jsonByte)) | |
} | |
func (u *User) MarshalJSON() ([]byte, error) { | |
// Get old struct fields | |
uType := reflect.TypeOf(u).Elem() | |
var fields []reflect.StructField | |
// Scan and collect all fields converting any that have a "db" tag | |
for i := 0; i < uType.NumField(); i++ { | |
f := uType.Field(i) | |
if dbkey, ok := f.Tag.Lookup("db"); ok && dbkey != "" { | |
f.Tag = reflect.StructTag(fmt.Sprintf(`json:"%s"`, dbkey)) | |
} | |
fields = append(fields, f) | |
} | |
newType := reflect.StructOf(fields) | |
newTypeInstance := reflect.New(newType).Elem() | |
origInstance := reflect.ValueOf(u).Elem() | |
// Copy over the values | |
for i := 0; i < origInstance.NumField(); i++ { | |
newTypeInstance.Field(i).Set(origInstance.Field(i)) | |
} | |
return json.Marshal(newTypeInstance.Interface()) | |
// Manual method picking out a few fields | |
// userNameField, ok := uType.FieldByName("Username") | |
// if !ok { return nil, errors.New("could not find Username field") } | |
// // Manipulate username field struct tag | |
// dbTagUser, _ := userNameField.Tag.Lookup("db") | |
// fmt.Printf("dbTagUser %#v\n", dbTagUser) | |
// if dbTagUser != "" { | |
// userNameField.Tag = reflect.StructTag(fmt.Sprintf(`json:"%s"`, dbTagUser)) | |
// } | |
// | |
// fldDisplayName, ok := uType.FieldByName("DisplayName") | |
// if !ok { return nil, errors.New("could not find DisplayName field") } | |
// // Manipulate username field struct tag | |
// dbTagDisplayName, _ := fldDisplayName.Tag.Lookup("db") | |
// if dbTagDisplayName != "" { | |
// fldDisplayName.Tag = reflect.StructTag(fmt.Sprintf(`json:"%s"`, dbTagDisplayName)) | |
// } | |
// | |
// fldEmail, _ := uType.FieldByName("Email") | |
// | |
// // Make a new struct from the provided fields. Fields must match original so copy below can work | |
// | |
// newType := reflect.StructOf([]reflect.StructField{userNameField, fldDisplayName, fldEmail}) | |
// | |
// // Copy over the values | |
// origInstance := reflect.ValueOf(u).Elem() | |
// newTypeInstance := reflect.New(newType).Elem() | |
// for i := 0; i < origInstance.NumField(); i++ { | |
// newTypeInstance.Field(i).Set(origInstance.Field(i)) | |
// } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment