87 lines
2.4 KiB
Go
87 lines
2.4 KiB
Go
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, ", ") // 用换行符连接每个错误信息
|
|
}
|