Initial import
This commit is contained in:
134
struct.go
Normal file
134
struct.go
Normal file
@@ -0,0 +1,134 @@
|
||||
package commons
|
||||
|
||||
import (
|
||||
"log"
|
||||
"reflect"
|
||||
"strings"
|
||||
// "encoding/json"
|
||||
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
// MapToStruct will convert a map[string]any to a struct.
|
||||
func MapToStruct(m map[string]any, o any) error {
|
||||
b, err := bson.Marshal(m)
|
||||
if err != nil {
|
||||
log.Printf("Failed marshal %v", err)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
err = bson.Unmarshal(b, o)
|
||||
if err != nil {
|
||||
log.Printf("Failed to unmarshal %v", err)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MapIsSubset given two map[string]any m1 and m2 will determine if m1 is a subset of m2.
|
||||
// Only fields' name is evaluated not their values.
|
||||
func MapIsSubset(subset, superset any) bool {
|
||||
sub := subset.(map[string]any)
|
||||
sup := superset.(map[string]any)
|
||||
|
||||
isSubset := true
|
||||
|
||||
for k, _ := range sub {
|
||||
_, ok := sup[k]
|
||||
if !ok {
|
||||
isSubset = false
|
||||
}
|
||||
}
|
||||
|
||||
return isSubset
|
||||
}
|
||||
|
||||
// MapIsSubsetOfStruct given a map[string]any and a struct will determine if the map is a subset of the struct.
|
||||
// Only fields' name is evaluated not their values.
|
||||
func MapIsSubsetOfStruct(m map[string]any, s any) bool {
|
||||
v := reflect.ValueOf(s)
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem() // Dereference if it's a pointer
|
||||
}
|
||||
|
||||
// Ensure we are working with a struct
|
||||
if v.Kind() != reflect.Struct {
|
||||
return false
|
||||
}
|
||||
|
||||
isSubset := true
|
||||
|
||||
t := v.Type()
|
||||
for key := range m {
|
||||
|
||||
// FieldByName only finds exported fields
|
||||
if _, found := t.FieldByName(key); !found {
|
||||
isSubset = false
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return isSubset
|
||||
}
|
||||
|
||||
// StructHasJsonName determines if a struct has the given json tag name.
|
||||
func StructHasJsonName(s any, targetName string) bool {
|
||||
t := reflect.TypeOf(s)
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
tag := field.Tag.Get("json")
|
||||
|
||||
// The name is the first part before any commas (e.g., "user_id,omitempty")
|
||||
name := strings.Split(tag, ",")[0]
|
||||
|
||||
if name == targetName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// StructHasJsonName determines if a struct has the given bson tag name.
|
||||
func StructHasBsonName(s any, targetName string) bool {
|
||||
t := reflect.TypeOf(s)
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
tag := field.Tag.Get("bson")
|
||||
|
||||
// The name is the first part before any commas (e.g., "user_id,omitempty")
|
||||
name := strings.Split(tag, ",")[0]
|
||||
|
||||
if name == targetName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// StructCopyMatching copies the fields of one struct to another only if they have the same name and type.
|
||||
func StructCopyMatching(source, target any) {
|
||||
sVal := reflect.ValueOf(source).Elem()
|
||||
tVal := reflect.ValueOf(target).Elem()
|
||||
|
||||
for i := 0; i < sVal.NumField(); i++ {
|
||||
sField := sVal.Type().Field(i)
|
||||
tField, ok := tVal.Type().FieldByName(sField.Name)
|
||||
|
||||
if ok && sField.Type == tField.Type {
|
||||
tVal.FieldByName(sField.Name).Set(sVal.Field(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user