package schema import ( "encoding/json" "fmt" "github.com/xeipuuv/gojsonschema" "os" "path/filepath" "strings" ) // ValidationResult 结构用于保存校验结果 type ValidationResult struct { Valid bool Data map[string]interface{} Errors string } // 校验函数:接受 schema 文件路径和 JSON 数据 func ValidateJSONWithSchema(schemaFileName string, data []byte) (ValidationResult, error) { // 获取项目根目录 rootPath, err := os.Getwd() if err != nil { return ValidationResult{}, fmt.Errorf("无法获取项目根目录: %v", err) } // 构建本地 Schema 文件路径 schemaPath := filepath.Join(rootPath, "internal", "schema", schemaFileName) // 将文件路径转换为 file:// URI 格式 schemaURI := "file:///" + filepath.ToSlash(schemaPath) // 读取 schema 文件,通过 URI 加载 schemaLoader := gojsonschema.NewReferenceLoader(schemaURI) // 将传入的 []byte 数据转为 JSON Loader jsonLoader := gojsonschema.NewBytesLoader(data) // 执行校验 result, err := gojsonschema.Validate(schemaLoader, jsonLoader) if err != nil { return ValidationResult{}, fmt.Errorf("校验过程中出错: %v", err) } // 初始化返回结果 validationResult := ValidationResult{ Valid: result.Valid(), Data: make(map[string]interface{}), Errors: "", } // 如果校验失败,收集并自定义错误信息 if !result.Valid() { errorMessages := collectErrors(result.Errors()) validationResult.Errors = formatErrors(errorMessages) return validationResult, nil } // 校验成功,解析 JSON if err := json.Unmarshal(data, &validationResult.Data); err != nil { return validationResult, fmt.Errorf("JSON 解析出错: %v", err) } return validationResult, nil } // collectErrors 自定义处理错误信息 func collectErrors(errors []gojsonschema.ResultError) []string { var errorMessages []string for _, err := range errors { // 从 Details() 中获取真正的字段名 details := err.Details() fieldName, ok := details["property"].(string) if !ok { fieldName = err.Field() // 默认使用 err.Field(),如果 property 不存在 } errorMessages = append(errorMessages, fmt.Sprintf("%s: %s", fieldName, err.Description())) } return errorMessages } // formatErrors 将错误列表格式化为美观的字符串 func formatErrors(errors []string) string { return strings.Join(errors, ", ") // 用换行符连接每个错误信息 }