package fieldx import ( "encoding/json" "fmt" "strings" "git.fsdpf.net/go/reflux" ) // FieldType 定义字段类型 type FieldType string const ( // FieldTypeString 固定字符串值 FieldTypeString FieldType = "string" // FieldTypeField 从传入对象中获取字段值 FieldTypeField FieldType = "field" // FieldTypeObject 嵌套对象类型 FieldTypeObject FieldType = "object" ) // Field 定义单个字段的 Schema type Field struct { // Type 字段类型: string, field, object Type FieldType `json:"type"` // Value 字段值,根据 Type 不同含义不同: // - string: 固定字符串值 // - field: 要获取的字段路径 // - object: 忽略,使用 Fields Value string `json:"value,omitempty"` // Fields 当 Type 为 object 时,包含嵌套的字段定义 Fields Schema `json:"fields,omitempty"` } // Schema 定义字段映射表 type Schema map[string]Field // Generate 根据 Schema 生成对象 // source: 源数据对象,用于 FieldTypeField 类型获取字段值 // 返回生成的 map[string]any 对象,如果 source 无效或处理失败则返回错误 func (s Schema) Generate(source any) (result map[string]any, err error) { // 捕获 reflux.New 可能产生的 panic defer func() { if r := recover(); r != nil { result = nil err = fmt.Errorf("failed to wrap source data: %v", r) } }() // 使用 reflux 包装源数据,提供统一的访问接口 rfx := reflux.New(source) result = make(map[string]any) err = s.generateFields(rfx, result) return result, err } // generateFields 递归生成字段 func (s Schema) generateFields(source reflux.R, target map[string]any) error { for fieldName, field := range s { value, err := field.generateValue(source) if err != nil { return fmt.Errorf("failed to generate field %s: %w", fieldName, err) } target[fieldName] = value } return nil } // generateValue 生成字段值 func (f Field) generateValue(source reflux.R) (any, error) { switch f.Type { case FieldTypeString: return f.Value, nil case FieldTypeField: return getFieldValue(f.Value, source) case FieldTypeObject: // 嵌套对象 nestedResult := make(map[string]any) err := f.Fields.generateFields(source, nestedResult) if err != nil { return nil, err } return nestedResult, nil default: return nil, fmt.Errorf("unsupported field type: %s", f.Type) } } // getFieldValue 从源对象获取字段值 // 支持点号分隔的路径,如 "user.name" func getFieldValue(path string, source reflux.R) (any, error) { // 分割路径 parts := strings.Split(path, ".") // 检查字段是否存在 if !source.Exists(parts...) { return nil, fmt.Errorf("field not found: %s", path) } // 获取值 accessor := source.Get(parts...) return accessor.Any(), nil } // SchemaFromJSON 从 JSON 字符串创建 Schema // 这是最简单直接的方式 func SchemaFromJSON(jsonStr string) (Schema, error) { var schema Schema err := json.Unmarshal([]byte(jsonStr), &schema) if err != nil { return nil, fmt.Errorf("failed to unmarshal JSON: %w", err) } return schema, nil } // SchemaFromMap 从 map[string]any 创建 Schema // 支持从 JSON 反序列化后的 map 转换 func SchemaFromMap(data map[string]any) (Schema, error) { schema := make(Schema) for key, value := range data { field, err := fieldFromMap(value) if err != nil { return nil, err } schema[key] = field } return schema, nil } // fieldFromMap 从 map[string]any 创建 Field func fieldFromMap(data any) (Field, error) { m, ok := data.(map[string]any) if !ok { return Field{}, fmt.Errorf("invalid field data: expected map[string]any, got %T", data) } field := Field{} // 解析 type if typeVal, ok := m["type"]; ok { if typeStr, ok := typeVal.(string); ok { field.Type = FieldType(typeStr) } } // 解析 value if value, ok := m["value"]; ok { if valueStr, ok := value.(string); ok { field.Value = valueStr } } // 解析 fields (嵌套) if fields, ok := m["fields"]; ok { if fieldsMap, ok := fields.(map[string]any); ok { nestedSchema, err := SchemaFromMap(fieldsMap) if err != nil { return Field{}, err } field.Fields = nestedSchema } } return field, nil }