增加部分数据验证转化逻辑
This commit is contained in:
		@ -15,6 +15,7 @@ package define
 | 
			
		||||
type FieldRule struct {
 | 
			
		||||
	Path                   string                `json:"path"`                     // 字段路径
 | 
			
		||||
	Type                   string                `json:"type"`                     // 数据类型, 具体枚举值参见 git.zhangdeman.cn/zhangdeman/consts
 | 
			
		||||
	DisableRewrite         bool                  `json:"disable_rewrite"`          // 验证完相关数据类型之后, 不要重新给字段赋值
 | 
			
		||||
	DefaultValue           string                `json:"default_value"`            // 默认值, 统一以字符串传入, 会转为最终设置的类型
 | 
			
		||||
	IsRequired             bool                  `json:"is_required"`              // 是否必传
 | 
			
		||||
	AllowEmpty             bool                  `json:"allow_empty"`              // 必传时空字符串是否合法
 | 
			
		||||
@ -30,8 +31,8 @@ type FieldRule struct {
 | 
			
		||||
//
 | 
			
		||||
// Date : 10:58 2024/4/29
 | 
			
		||||
type RequiredCondition struct {
 | 
			
		||||
	DependOnField       string `json:"depend_on_field"`        // 依赖数据园中的那一个字段
 | 
			
		||||
	DependOnFieldStatus string `json:"depend_on_field_status"` // 依赖数据状态 : NOT_FOUND / IS_NIL / IS_ZERO / IS_EMPTY / IS_FALSE
 | 
			
		||||
	DependOnField       string   `json:"depend_on_field"`        // 依赖数据园中的那一个字段
 | 
			
		||||
	DependOnFieldStatus []string `json:"depend_on_field_status"` // 依赖数据状态 : NOT_FOUND / IS_NIL / IS_ZERO / IS_EMPTY / IS_FALSE
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ValueLimit 取值的限制
 | 
			
		||||
@ -40,11 +41,11 @@ type RequiredCondition struct {
 | 
			
		||||
//
 | 
			
		||||
// Date : 11:15 2024/4/29
 | 
			
		||||
type ValueLimit struct {
 | 
			
		||||
	String *StringValueLimit `json:"string"` // 字符串值的限制
 | 
			
		||||
	Int    *IntValueLimit    `json:"int"`    // int数据验证
 | 
			
		||||
	Float  *FloatValueLimit  `json:"float"`  // 浮点数据
 | 
			
		||||
	Slice  *SliceValueLimit  `json:"slice"`  // 数组
 | 
			
		||||
	Map    *MapValueLimit    `json:"map"`    // map验证
 | 
			
		||||
	EnumList []string          `json:"enum_list"` // 枚举值列表, 仅对 int / float / string 生效
 | 
			
		||||
	Min      *float64          `json:"min"`       // 最小值(包含), 对于 int/float, 此值为最小取值, 对于int/map/slice辞职问最小长度
 | 
			
		||||
	Max      *float64          `json:"max"`       // 最大值(不包含), 对于 int/float, 此值为最大取值, 对于int/map/slice辞职问最大长度
 | 
			
		||||
	String   *StringValueLimit `json:"string"`    // 字符串值的限制
 | 
			
		||||
	Map      *MapValueLimit    `json:"map"`       // map验证
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringValueLimit 字符串类型值的限制
 | 
			
		||||
@ -53,43 +54,8 @@ type ValueLimit struct {
 | 
			
		||||
//
 | 
			
		||||
// Date : 11:16 2024/4/29
 | 
			
		||||
type StringValueLimit struct {
 | 
			
		||||
	MinLength         int64    `json:"min_length"`           // 最小长度(包含)
 | 
			
		||||
	MaxLength         int64    `json:"max_length"`           // 最大长度(不包含)
 | 
			
		||||
	AutoTrimSpace     bool     `json:"auto_trim_space"`      // 自动去除前后空格
 | 
			
		||||
	IncludeSubStrList []string `json:"include_sub_str_list"` // 必须包含指定的子串
 | 
			
		||||
	EnumList          []string `json:"enum_list"`            // 枚举值列表
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IntValueLimit ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 11:22 2024/4/29
 | 
			
		||||
type IntValueLimit struct {
 | 
			
		||||
	Min      *int64  `json:"min"`       // 最小值(包含)
 | 
			
		||||
	Max      *int64  `json:"max"`       // 最大值(不包含)
 | 
			
		||||
	EnumList []int64 `json:"enum_list"` // 枚举值列表
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FloatValueLimit ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 11:22 2024/4/29
 | 
			
		||||
type FloatValueLimit struct {
 | 
			
		||||
	Min      *float64  `json:"min"`       // 最小值(包含)
 | 
			
		||||
	Max      *float64  `json:"max"`       // 最大值(不包含)
 | 
			
		||||
	EnumList []float64 `json:"enum_list"` // 枚举值列表
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SliceValueLimit 数组限制
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 11:23 2024/4/29
 | 
			
		||||
type SliceValueLimit struct {
 | 
			
		||||
	MinLength int64 `json:"min_length"` // 最小长度(包含)
 | 
			
		||||
	MaxLength int64 `json:"max_length"` // 最大长度(不包含)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MapValueLimit map数据的限制
 | 
			
		||||
@ -98,7 +64,5 @@ type SliceValueLimit struct {
 | 
			
		||||
//
 | 
			
		||||
// Date : 11:23 2024/4/29
 | 
			
		||||
type MapValueLimit struct {
 | 
			
		||||
	MinLength        int64    `json:"min_length"`         // 最小长度(包含)
 | 
			
		||||
	MaxLength        int64    `json:"max_length"`         // 最大长度(不包含)
 | 
			
		||||
	IncludeFieldList []string `json:"include_field_list"` // 必须存在的字段列表
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										19
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								go.mod
									
									
									
									
									
								
							@ -2,4 +2,21 @@ module git.zhangdeman.cn/gateway/validator
 | 
			
		||||
 | 
			
		||||
go 1.22.2
 | 
			
		||||
 | 
			
		||||
require git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240429055735-7d7191726f0c // indirect
 | 
			
		||||
require (
 | 
			
		||||
	git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240429082641-eeef7e967d00 // indirect
 | 
			
		||||
	git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211 // indirect
 | 
			
		||||
	git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240325080031-1f58204e8687 // indirect
 | 
			
		||||
	git.zhangdeman.cn/zhangdeman/util v0.0.0-20231227095334-7eb5cdbf9253 // indirect
 | 
			
		||||
	git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240422034417-8c922be06d95 // indirect
 | 
			
		||||
	github.com/BurntSushi/toml v1.3.2 // indirect
 | 
			
		||||
	github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
 | 
			
		||||
	github.com/go-ini/ini v1.67.0 // indirect
 | 
			
		||||
	github.com/mitchellh/go-homedir v1.1.0 // indirect
 | 
			
		||||
	github.com/mozillazg/go-pinyin v0.20.0 // indirect
 | 
			
		||||
	github.com/spaolacci/murmur3 v1.1.0 // indirect
 | 
			
		||||
	github.com/tidwall/gjson v1.17.1 // indirect
 | 
			
		||||
	github.com/tidwall/match v1.1.1 // indirect
 | 
			
		||||
	github.com/tidwall/pretty v1.2.1 // indirect
 | 
			
		||||
	github.com/tidwall/sjson v1.2.5 // indirect
 | 
			
		||||
	gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										38
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								go.sum
									
									
									
									
									
								
							@ -1,2 +1,40 @@
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240429055735-7d7191726f0c h1:n+n49onVpIgemvRdX4XnUB5psWh/NZ/qYkapCbJ4AYA=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240429055735-7d7191726f0c/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240429080251-9cd57471a8f5 h1:6JsrADIXKWb7ZzaqAFlNpfL5ynu8m1X8Tju8h63mN0Y=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240429080251-9cd57471a8f5/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240429082641-eeef7e967d00 h1:bOPZXYX9CfnZBPqkQnzgwnuC1uyXBivSY0nmV4HabXg=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240429082641-eeef7e967d00/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211 h1:I/wOsRpCSRkU9vo1u703slQsmK0wnNeZzsWQOGtIAG0=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211/go.mod h1:SrtvrQRdzt+8KfYzvosH++gWxo2ShPTzR1m3VQ6uX7U=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240325080031-1f58204e8687 h1:uQcGqdzi4UdpZlp4f4FUPeBqoygP58pEKJkmN3ROsE0=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240325080031-1f58204e8687/go.mod h1:gf7SW2TXATgux8pfdFedMkXWv2515OtIIM/5c4atkFw=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20231227095334-7eb5cdbf9253 h1:GO3oZa5a2sqwAzGcLDJtQzmshSWRmoP7IDS8bwFqvC4=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20231227095334-7eb5cdbf9253/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240422034417-8c922be06d95 h1:3lO4ap9p7kEA+4yL5ojG9mAWsz5sY28Nu2tSzAZEehw=
 | 
			
		||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240422034417-8c922be06d95/go.mod h1:Fo4XOiZPua4E4/Qzy3ZYS5zyd15bS/lsb3t6S6PQFGY=
 | 
			
		||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
 | 
			
		||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
 | 
			
		||||
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
 | 
			
		||||
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
 | 
			
		||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
 | 
			
		||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
 | 
			
		||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
 | 
			
		||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 | 
			
		||||
github.com/mozillazg/go-pinyin v0.20.0 h1:BtR3DsxpApHfKReaPO1fCqF4pThRwH9uwvXzm+GnMFQ=
 | 
			
		||||
github.com/mozillazg/go-pinyin v0.20.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
 | 
			
		||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
 | 
			
		||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 | 
			
		||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
 | 
			
		||||
github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
 | 
			
		||||
github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
 | 
			
		||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
 | 
			
		||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
 | 
			
		||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
 | 
			
		||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
 | 
			
		||||
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
 | 
			
		||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
 | 
			
		||||
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
 | 
			
		||||
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
			
		||||
 | 
			
		||||
@ -25,83 +25,15 @@ func NewDefaultFieldRule(path string, dataType string, isRequired bool, defaultV
 | 
			
		||||
		AllowZero:              true,
 | 
			
		||||
		RequiredConditionGroup: make([][]define.RequiredCondition, 0),
 | 
			
		||||
		ValueLimit: &define.ValueLimit{
 | 
			
		||||
			String: nil,
 | 
			
		||||
			Int:    nil,
 | 
			
		||||
			Float:  nil,
 | 
			
		||||
			Slice:  nil,
 | 
			
		||||
			Map:    nil,
 | 
			
		||||
			EnumList: make([]string, 0),
 | 
			
		||||
			Min:      nil,
 | 
			
		||||
			Max:      nil,
 | 
			
		||||
			String: &define.StringValueLimit{
 | 
			
		||||
				AutoTrimSpace:     true,
 | 
			
		||||
				IncludeSubStrList: make([]string, 0),
 | 
			
		||||
			},
 | 
			
		||||
			Map: &define.MapValueLimit{IncludeFieldList: make([]string, 0)},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDefaultStringValueLimit ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 12:22 2024/4/29
 | 
			
		||||
func NewDefaultStringValueLimit(minLength int64, maxLength int64) *define.StringValueLimit {
 | 
			
		||||
	l := &define.StringValueLimit{
 | 
			
		||||
		MinLength:         minLength,
 | 
			
		||||
		MaxLength:         maxLength,
 | 
			
		||||
		AutoTrimSpace:     true,
 | 
			
		||||
		IncludeSubStrList: make([]string, 0),
 | 
			
		||||
		EnumList:          make([]string, 0),
 | 
			
		||||
	}
 | 
			
		||||
	return l
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDefaultIntValueLimit ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 12:24 2024/4/29
 | 
			
		||||
func NewDefaultIntValueLimit(min *int64, max *int64) *define.IntValueLimit {
 | 
			
		||||
	l := &define.IntValueLimit{
 | 
			
		||||
		Min:      min,
 | 
			
		||||
		Max:      max,
 | 
			
		||||
		EnumList: make([]int64, 0),
 | 
			
		||||
	}
 | 
			
		||||
	return l
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDefaultFloatValueLimit ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 12:27 2024/4/29
 | 
			
		||||
func NewDefaultFloatValueLimit(min *float64, max *float64) *define.FloatValueLimit {
 | 
			
		||||
	l := &define.FloatValueLimit{
 | 
			
		||||
		Min:      min,
 | 
			
		||||
		Max:      max,
 | 
			
		||||
		EnumList: make([]float64, 0),
 | 
			
		||||
	}
 | 
			
		||||
	return l
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDefaultSliceValueLimit ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 12:30 2024/4/29
 | 
			
		||||
func NewDefaultSliceValueLimit(minLength int64, maxLength int64) *define.SliceValueLimit {
 | 
			
		||||
	l := &define.SliceValueLimit{
 | 
			
		||||
		MinLength: minLength,
 | 
			
		||||
		MaxLength: maxLength,
 | 
			
		||||
	}
 | 
			
		||||
	return l
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDefaultMapValueLimit ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 12:30 2024/4/29
 | 
			
		||||
func NewDefaultMapValueLimit(minLength int64, maxLength int64) *define.MapValueLimit {
 | 
			
		||||
	l := &define.MapValueLimit{
 | 
			
		||||
		MinLength:        minLength,
 | 
			
		||||
		MaxLength:        maxLength,
 | 
			
		||||
		IncludeFieldList: make([]string, 0),
 | 
			
		||||
	}
 | 
			
		||||
	return l
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										350
									
								
								run.go
									
									
									
									
									
								
							
							
						
						
									
										350
									
								
								run.go
									
									
									
									
									
								
							@ -7,6 +7,354 @@
 | 
			
		||||
// Date : 2024-04-29 10:51
 | 
			
		||||
package validator
 | 
			
		||||
 | 
			
		||||
func Run() {
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"git.zhangdeman.cn/gateway/validator/define"
 | 
			
		||||
	"git.zhangdeman.cn/zhangdeman/consts"
 | 
			
		||||
	"git.zhangdeman.cn/zhangdeman/serialize"
 | 
			
		||||
	"git.zhangdeman.cn/zhangdeman/util"
 | 
			
		||||
	"git.zhangdeman.cn/zhangdeman/wrapper"
 | 
			
		||||
	"github.com/tidwall/gjson"
 | 
			
		||||
	"github.com/tidwall/sjson"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// RunForStruct 验证结构体
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 14:18 2024/4/29
 | 
			
		||||
func RunForStruct(sourceData interface{}, ruleList []*define.FieldRule) (map[string]interface{}, error) {
 | 
			
		||||
	if nil == sourceData {
 | 
			
		||||
		return map[string]interface{}{}, nil
 | 
			
		||||
	}
 | 
			
		||||
	byteData, _ := json.Marshal(sourceData)
 | 
			
		||||
	var (
 | 
			
		||||
		sourceMapData map[string]interface{}
 | 
			
		||||
		err           error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	d := json.NewDecoder(bytes.NewReader(byteData))
 | 
			
		||||
	d.UseNumber()
 | 
			
		||||
	if err = d.Decode(&sourceMapData); nil != err {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err = Run(sourceMapData, ruleList); nil != err {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return sourceMapData, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Run 运行参数验证
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 14:13 2024/4/29
 | 
			
		||||
func Run(sourceData map[string]interface{}, ruleList []*define.FieldRule) error {
 | 
			
		||||
	if nil == sourceData || len(sourceData) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	byteData, _ := json.Marshal(sourceData)
 | 
			
		||||
	for _, itemRule := range ruleList {
 | 
			
		||||
		if len(itemRule.Path) == 0 {
 | 
			
		||||
			// 未指定验证数据位置
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		inputFieldVal := gjson.GetBytes(byteData, itemRule.Path)
 | 
			
		||||
		if formatRule, err := validate(byteData, inputFieldVal, itemRule); nil != err {
 | 
			
		||||
			return err
 | 
			
		||||
		} else {
 | 
			
		||||
			if !itemRule.DisableRewrite {
 | 
			
		||||
				// 更新数据
 | 
			
		||||
				byteData, _ = sjson.SetBytes(byteData, itemRule.Path, formatRule)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	sourceData = make(map[string]interface{})
 | 
			
		||||
	d := json.NewDecoder(bytes.NewReader(byteData))
 | 
			
		||||
	d.UseNumber()
 | 
			
		||||
	if err := d.Decode(&sourceData); nil != err {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getDataStatus 获取数据状态
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 15:59 2024/4/29
 | 
			
		||||
func getDataStatus(val gjson.Result, dataType string) string {
 | 
			
		||||
	if !val.Exists() {
 | 
			
		||||
		return consts.DataStatusNotFound
 | 
			
		||||
	}
 | 
			
		||||
	switch dataType {
 | 
			
		||||
	case consts.DataTypeString:
 | 
			
		||||
		if len(val.String()) == 0 {
 | 
			
		||||
			return consts.DataStatusIsEmpty
 | 
			
		||||
		}
 | 
			
		||||
	case consts.DataTypeFloat:
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case consts.DataTypeInt:
 | 
			
		||||
		if val.Float() == 0 {
 | 
			
		||||
			return consts.DataStatusIsZero
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		if strings.HasPrefix(dataType, "[]") {
 | 
			
		||||
			// 数组
 | 
			
		||||
			if len(val.Array()) == 0 {
 | 
			
		||||
				return consts.DataStatusIsEmpty
 | 
			
		||||
			}
 | 
			
		||||
		} else if strings.HasPrefix(dataType, "map") {
 | 
			
		||||
			// 对象
 | 
			
		||||
			if len(val.Map()) == 0 {
 | 
			
		||||
				return consts.DataStatusIsEmpty
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// validate 验证字段
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 14:32 2024/4/29
 | 
			
		||||
func validate(sourceData []byte, val gjson.Result, rule *define.FieldRule) (interface{}, error) {
 | 
			
		||||
	inputVal := val.Value()
 | 
			
		||||
	if !val.Exists() {
 | 
			
		||||
		if rule.IsRequired {
 | 
			
		||||
			return nil, fmt.Errorf("%v : field is required, but not found", rule.Path)
 | 
			
		||||
		}
 | 
			
		||||
		// TODO : 验证有条件必传
 | 
			
		||||
		inputVal = rule.DefaultValue
 | 
			
		||||
	} else {
 | 
			
		||||
		if inputVal == nil {
 | 
			
		||||
			if !rule.AllowNil {
 | 
			
		||||
				return nil, fmt.Errorf("%v : field value is nil, but not allowed", rule.Path)
 | 
			
		||||
			}
 | 
			
		||||
			inputVal = rule.DefaultValue
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return handleData(inputVal, rule)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// handleData 处理数据
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 14:43 2024/4/29
 | 
			
		||||
func handleData(inputVal interface{}, rule *define.FieldRule) (interface{}, error) {
 | 
			
		||||
	switch rule.Type {
 | 
			
		||||
	case consts.DataTypeAny: // 任意类型
 | 
			
		||||
		return inputVal, nil
 | 
			
		||||
	case consts.DataTypeFloat: // float数据
 | 
			
		||||
		return handleFloat(inputVal, rule)
 | 
			
		||||
	case consts.DataTypeInt: // int类型
 | 
			
		||||
		return handleInt(inputVal, rule)
 | 
			
		||||
	case consts.DataTypeString: // 字符串处理
 | 
			
		||||
		return handleString(inputVal, rule)
 | 
			
		||||
	case consts.DataTypeMapStrFloat, consts.DataTypeMapStrBool,
 | 
			
		||||
		consts.DataTypeMapStrInt, consts.DataTypeMapStrUint:
 | 
			
		||||
		// 一律按照 map[string]float64处理
 | 
			
		||||
		return handleMapStringFloat(inputVal, rule)
 | 
			
		||||
	case consts.DataTypeMapStrAny: // 对象结构
 | 
			
		||||
		return handleMapStringAny(inputVal, rule)
 | 
			
		||||
	case consts.DataTypeMapStrSlice: // map列表
 | 
			
		||||
 | 
			
		||||
	case consts.DataTypeMapAnyAny: // 任意类型map
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// handleFloat 处理float数据
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 15:29 2024/4/29
 | 
			
		||||
func handleFloat(inputVal interface{}, rule *define.FieldRule) (float64, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		err        error
 | 
			
		||||
		formatData float64
 | 
			
		||||
	)
 | 
			
		||||
	if err = util.ConvertAssign(&formatData, inputVal); nil != err {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	if !rule.AllowZero {
 | 
			
		||||
		return 0, fmt.Errorf("%v : field type is float, but zero val is not allowed", rule.Path)
 | 
			
		||||
	}
 | 
			
		||||
	if nil == rule.ValueLimit {
 | 
			
		||||
		return formatData, nil
 | 
			
		||||
	}
 | 
			
		||||
	if nil != rule.ValueLimit.Min && formatData < *rule.ValueLimit.Min {
 | 
			
		||||
		return 0, fmt.Errorf("%v : field type is float, min val is %v, real val is %v", rule.Path, *rule.ValueLimit.Min, formatData)
 | 
			
		||||
	}
 | 
			
		||||
	if nil != rule.ValueLimit.Max && formatData > *rule.ValueLimit.Max {
 | 
			
		||||
		return 0, fmt.Errorf("%v : field type is float, max val is %v, real val is %v", rule.Path, *rule.ValueLimit.Max, formatData)
 | 
			
		||||
	}
 | 
			
		||||
	if len(rule.ValueLimit.EnumList) > 0 {
 | 
			
		||||
		if wrapper.ArrayType(rule.ValueLimit.EnumList).Has(formatData) < 0 {
 | 
			
		||||
			return 0, fmt.Errorf("%v : field type is float, real val is %v, is not in enum list", rule.Path, formatData)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return formatData, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// handleInt ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 15:36 2024/4/29
 | 
			
		||||
func handleInt(inputVal interface{}, rule *define.FieldRule) (int64, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		err        error
 | 
			
		||||
		formatData int64
 | 
			
		||||
	)
 | 
			
		||||
	if err = util.ConvertAssign(&formatData, inputVal); nil != err {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	if _, err = handleFloat(formatData, rule); nil != err {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	return formatData, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// handleString ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 15:53 2024/4/29
 | 
			
		||||
func handleString(inputVal interface{}, rule *define.FieldRule) (string, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		err        error
 | 
			
		||||
		formatData string
 | 
			
		||||
	)
 | 
			
		||||
	if err = util.ConvertAssign(&formatData, inputVal); nil != err {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	if nil == rule.ValueLimit {
 | 
			
		||||
		return formatData, nil
 | 
			
		||||
	}
 | 
			
		||||
	if nil != rule.ValueLimit.Min {
 | 
			
		||||
		if float64(len(formatData)) < *rule.ValueLimit.Min {
 | 
			
		||||
			return "", fmt.Errorf("%v : data type is string, min length is %v, real length is %v", rule.Path, *rule.ValueLimit.Min, len(formatData))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if nil != rule.ValueLimit.Max {
 | 
			
		||||
		if float64(len(formatData)) >= *rule.ValueLimit.Max {
 | 
			
		||||
			return "", fmt.Errorf("%v : data type is string, max length is %v, real length is %v", rule.Path, *rule.ValueLimit.Max, len(formatData))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(rule.ValueLimit.EnumList) > 0 {
 | 
			
		||||
		if wrapper.ArrayType(rule.ValueLimit.EnumList).Has(formatData) < 0 {
 | 
			
		||||
			return "", fmt.Errorf("%v : data type is string, not in enum list, real val is %v", rule.Path, formatData)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return formatData, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// handleMapStringFloat ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 16:38 2024/4/29
 | 
			
		||||
func handleMapStringFloat(inputVal interface{}, rule *define.FieldRule) (map[string]float64, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		err error
 | 
			
		||||
		res map[string]float64
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if err = strOrMapConvert(inputVal, &res); nil != err {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dataFieldTable := make(map[string]string)
 | 
			
		||||
	for k, _ := range res {
 | 
			
		||||
		dataFieldTable[k] = k
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = validateMap(dataFieldTable, rule); nil != err {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// handleMapStringAny ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 17:19 2024/4/29
 | 
			
		||||
func handleMapStringAny(inputVal interface{}, rule *define.FieldRule) (map[string]interface{}, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		err error
 | 
			
		||||
		res map[string]interface{}
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if err = strOrMapConvert(inputVal, &res); nil != err {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dataFieldTable := make(map[string]string)
 | 
			
		||||
	for k, _ := range res {
 | 
			
		||||
		dataFieldTable[k] = k
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = validateMap(dataFieldTable, rule); nil != err {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// strOrMapConvert 字符串或map转map
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 17:26 2024/4/29
 | 
			
		||||
func strOrMapConvert(inputVal interface{}, receiver interface{}) error {
 | 
			
		||||
	var (
 | 
			
		||||
		err error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if inputValStr, ok := inputVal.(string); ok {
 | 
			
		||||
		if err = serialize.JSON.UnmarshalWithNumber([]byte(inputValStr), receiver); nil != err {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		byteData := serialize.JSON.MarshalForByte(inputVal)
 | 
			
		||||
		if err = serialize.JSON.UnmarshalWithNumber(byteData, receiver); nil != err {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// validateMap 验证map数据
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 17:21 2024/4/29
 | 
			
		||||
func validateMap(dataFieldTable map[string]string, rule *define.FieldRule) error {
 | 
			
		||||
	if nil == rule.ValueLimit {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if nil != rule.ValueLimit.Min && float64(len(dataFieldTable)) < *rule.ValueLimit.Min {
 | 
			
		||||
		return fmt.Errorf("%v : data type is map, min item cnt is %v, real item cnt is %v", rule.Path, *rule.ValueLimit.Min, len(dataFieldTable))
 | 
			
		||||
	}
 | 
			
		||||
	if nil != rule.ValueLimit.Max && float64(len(dataFieldTable)) >= *rule.ValueLimit.Max {
 | 
			
		||||
		return fmt.Errorf("%v : data type is map, max item cnt is %v, real item max is %v", rule.Path, *rule.ValueLimit.Max, len(dataFieldTable))
 | 
			
		||||
	}
 | 
			
		||||
	if nil != rule.ValueLimit.Map {
 | 
			
		||||
		for _, itemField := range rule.ValueLimit.Map.IncludeFieldList {
 | 
			
		||||
			if _, exist := dataFieldTable[itemField]; !exist {
 | 
			
		||||
				return fmt.Errorf("%v : data type is map, %v field is required, but not found", rule.Path, itemField)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										23
									
								
								run_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								run_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
// Package validator ...
 | 
			
		||||
//
 | 
			
		||||
// Description : validator ...
 | 
			
		||||
//
 | 
			
		||||
// Author : go_developer@163.com<白茶清欢>
 | 
			
		||||
//
 | 
			
		||||
// Date : 2024-04-29 14:14
 | 
			
		||||
package validator
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestRun(t *testing.T) {
 | 
			
		||||
	sourceData := map[string]interface{}{
 | 
			
		||||
		"name": "白茶清欢",
 | 
			
		||||
	}
 | 
			
		||||
	_ = Run(sourceData, nil)
 | 
			
		||||
	byteData, _ := json.Marshal(sourceData)
 | 
			
		||||
	fmt.Println(string(byteData))
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user