Skip to content

Instantly share code, notes, and snippets.

@roboncode
Last active July 19, 2024 02:12
Show Gist options
  • Save roboncode/d8592d3a6ca3704a92ff2c35baf8456a to your computer and use it in GitHub Desktop.
Save roboncode/d8592d3a6ca3704a92ff2c35baf8456a to your computer and use it in GitHub Desktop.
Firestore - GoLang Transform Struct To Map
package transform
import (
"reflect"
"strings"
"time"
)
const (
tagName = "firestore"
tagOmitEmpty = "omitempty"
delimiter = ","
)
type FirestoreMap map[string]interface{}
func ToFirestoreMap(value interface{}) FirestoreMap {
var result = parseData(value)
return result.(FirestoreMap)
}
func isZeroOfUnderlyingType(x interface{}) bool {
return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface())
}
func parseData(value interface{}) interface{} {
if value == nil {
return nil
}
var firestoreMap = FirestoreMap{}
var tag string
//var value interface{}
var fieldCount int
var val = reflect.ValueOf(value)
switch value.(type) {
case time.Time, *time.Time:
return value
}
switch val.Kind() {
case reflect.Map:
for _, key := range val.MapKeys() {
val := val.MapIndex(key)
firestoreMap[key.String()] = parseData(val.Interface())
}
return firestoreMap
case reflect.Ptr:
if val.IsNil() {
return nil
}
fieldCount = val.Elem().NumField()
for i := 0; i < fieldCount; i++ {
tag = val.Elem().Type().Field(i).Tag.Get(tagName)
value = val.Elem().Field(i).Interface()
setValue(firestoreMap, tag, value)
}
return firestoreMap
case reflect.Struct, reflect.Interface:
fieldCount = val.NumField()
for i := 0; i < fieldCount; i++ {
tag = val.Type().Field(i).Tag.Get(tagName)
value = val.Field(i).Interface()
setValue(firestoreMap, tag, value)
}
return firestoreMap
}
return value
}
func setValue(firestoreMap FirestoreMap, tag string, value interface{}) {
if tag == "" || tag == "-" || value == nil {
return
}
tagValues := strings.Split(tag, delimiter)
if strings.Contains(tag, tagOmitEmpty) {
if isZeroOfUnderlyingType(value) {
return
}
}
firestoreMap[tagValues[0]] = parseData(value)
}
@roboncode
Copy link
Author

type User struct {
	Id        string          `json:"id,omitempty" firestore:"id,omitempty"`
	Active    bool            `json:"active,omitempty" firestore:"active,omitempty"`
	Name      string          `json:"name,omitempty" firestore:"name,omitempty"`
	Email     string          `json:"email,omitempty" firestore:"email,omitempty"`
	Phone     string          `json:"phone,omitempty" firestore:"phone,omitempty"`
	CreatedAt *time.Time      `json:"createdAt,omitempty" firestore:"created_at,omitempty"`
}

@iMikio
Copy link

iMikio commented Oct 8, 2021

I forked your file and add serverTimestamp tag.
Thank you for your create.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment