package xun import ( "fmt" "reflect" "time" jsoniter "github.com/json-iterator/go" "github.com/yaoapp/yao/openapi/utils" ) // isNil checks whether a value is truly nil, handling the Go typed-nil-in-interface pitfall. // A nil map, slice, or pointer stored in an interface{} is not == nil in Go; // this helper uses reflect to detect that case. func isNil(v interface{}) bool { if v == nil { return true } rv := reflect.ValueOf(v) switch rv.Kind() { case reflect.Ptr, reflect.Map, reflect.Slice, reflect.Interface, reflect.Chan, reflect.Func: return rv.IsNil() } return false } // marshalJSONFields serialises each value in fields to a JSON string and writes // it into data. Truly-nil values (including typed nils) are skipped so the // database column keeps its SQL NULL / default. func marshalJSONFields(data map[string]interface{}, fields map[string]interface{}) error { for field, value := range fields { if isNil(value) { continue } jsonStr, err := jsoniter.MarshalToString(value) if err != nil { return fmt.Errorf("failed to marshal %s: %w", field, err) } data[field] = jsonStr } return nil } // Helper functions for type conversion func getString(data map[string]interface{}, key string) string { if v, ok := data[key].(string); ok { return v } return "" } func getBool(data map[string]interface{}, key string) bool { return utils.ToBool(data[key]) } func getInt(data map[string]interface{}, key string) int { return utils.ToInt(data[key]) } func getInt64(data map[string]interface{}, key string) int64 { v := data[key] if t, ok := v.(time.Time); ok { return t.UnixNano() } return utils.ToInt64(v) } func nanoToTime(ns int64) time.Time { return utils.NanoToTime(ns) } func timeToNano(t time.Time) int64 { return utils.TimeToNano(t) }