package utils import ( "fmt" "reflect" "strings" ) func MergeJSONObjects(dst, src map[string]interface{}) map[string]interface{} { result := make(map[string]interface{}) for k, v := range dst { result[k] = v } for key, value2 := range src { value1, exists := result[key] if exists { map1Val, map1IsMap := value1.(map[string]interface{}) map2Val, map2IsMap := value2.(map[string]interface{}) if map1IsMap && map2IsMap { result[key] = MergeJSONObjects(map1Val, map2Val) } else { // 覆盖第一个map中的值 result[key] = value2 } } else { // 添加新的键值对 result[key] = value2 } } return result } func StructToMap(in interface{}) (map[string]interface{}, error) { out := make(map[string]interface{}) v := reflect.ValueOf(in) // If it's a pointer, dereference it if v.Kind() == reflect.Ptr { v = v.Elem() } // Check if it's a struct if v.Kind() != reflect.Struct { return nil, fmt.Errorf("StructToMap only accepts structs or pointers to structs; got %T", v.Interface()) } t := v.Type() // Get the type of the struct for i := 0; i < v.NumField(); i++ { // Get the field Value and Type fieldV := v.Field(i) fieldT := t.Field(i) // Skip unexported fields if !fieldT.IsExported() { continue } // --- Handle JSON Tag --- tag := fieldT.Tag.Get("json") key := fieldT.Name // Default key is the field name omitempty := false if tag != "" { parts := strings.Split(tag, ",") tagName := parts[0] if tagName == "-" { // Skip fields tagged with "-" continue } if tagName != "" { key = tagName // Use tag name as key } // Check for omitempty option for _, part := range parts[1:] { if part == "omitempty" { omitempty = true break } } } // --- Handle omitempty --- val := fieldV.Interface() if omitempty && fieldV.IsZero() { continue // Skip zero-value fields if omitempty is set } // --- Handle Nested Structs/Pointers to Structs (Recursion) --- // Check for pointer first if fieldV.Kind() == reflect.Ptr { // If pointer is nil and omitempty is set, it was already skipped // If pointer is nil and omitempty is not set, add nil to map if fieldV.IsNil() { // Only add nil if omitempty is not set (already handled above) if !omitempty { out[key] = nil } continue // Move to next field } // If it points to a struct, dereference and recurse if fieldV.Elem().Kind() == reflect.Struct { nestedMap, err := StructToMap(fieldV.Interface()) // Pass the pointer if err != nil { // Decide how to handle nested errors, e.g., log or return fmt.Printf("Warning: could not convert nested struct pointer %s: %v\n", fieldT.Name, err) out[key] = val // Store original value on error? Or skip? } else { out[key] = nestedMap } continue // Move to next field after handling pointer } // If pointer to non-struct, just get the interface value (handled below) val = fieldV.Interface() // Use the actual pointer value } else if fieldV.Kind() == reflect.Struct { // If it's a struct (not a pointer), recurse nestedMap, err := StructToMap(fieldV.Interface()) // Pass the struct value if err != nil { fmt.Printf("Warning: could not convert nested struct %s: %v\n", fieldT.Name, err) out[key] = val // Store original value on error? Or skip? } else { out[key] = nestedMap } continue // Move to next field after handling struct } // Assign the value (primitive, slice, map, non-struct pointer, etc.) out[key] = val } return out, nil }