Skip to content

Commit

Permalink
Release v0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
TruenoCB committed Aug 12, 2023
0 parents commit 8677ee0
Show file tree
Hide file tree
Showing 26 changed files with 2,048 additions and 0 deletions.
Binary file added .DS_Store
Binary file not shown.
13 changes: 13 additions & 0 deletions binding/binding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package binding

import "net/http"

type Binding interface {
Name() string
Bind(*http.Request, interface{}) error
}

var (
JSON = jsonBinding{}
XML = xmlBinding{}
)
113 changes: 113 additions & 0 deletions binding/json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package binding

import (
"encoding/json"
"errors"
"fmt"
"net/http"
"reflect"
)

type jsonBinding struct {
DisallowUnknownFields bool
IsValidate bool
}

func (jsonBinding) Name() string {
return "json"
}

func (b jsonBinding) Bind(r *http.Request, obj interface{}) error {
body := r.Body
// post传参的内容 是放在 body中的
if body == nil {
return errors.New("invalid request")
}
decoder := json.NewDecoder(body)
if b.DisallowUnknownFields {
decoder.DisallowUnknownFields()
}
if b.IsValidate {
err := validateParam(obj, decoder)
if err != nil {
return err
}
} else {
err := decoder.Decode(obj)
if err != nil {
return err
}
}
return validate(obj)
}

func validateParam(obj interface{}, decoder *json.Decoder) error {

// 反射
valueOf := reflect.ValueOf(obj)
// 判断其是否为指针类型
if valueOf.Kind() != reflect.Ptr {
return errors.New("This argument must have a pointer type")
}
elem := valueOf.Elem().Interface()
of := reflect.ValueOf(elem)

switch of.Kind() {
case reflect.Struct:
return checkParam(of, obj, decoder)
case reflect.Slice, reflect.Array:
elem := of.Type().Elem()
if elem.Kind() == reflect.Struct {
return checkParamSlice(elem, obj, decoder)
}
default:
_ = decoder.Decode(obj)
}
return nil
}

func checkParamSlice(of reflect.Type, obj interface{}, decoder *json.Decoder) error {
mapValue := make([]map[string]interface{}, 0)
_ = decoder.Decode(&mapValue)
for i := 0; i < of.NumField(); i++ {
field := of.Field(i)
name := field.Name
jsonName := field.Tag.Get("json")
if jsonName != "" {
name = jsonName
}
required := field.Tag.Get("polevalidate")
for _, v := range mapValue {
value := v[name]
if value == nil && required == "required" {
return errors.New(fmt.Sprintf("filed [%s] is not exist,because [%s] is required", jsonName, jsonName))
}
}
}
b, _ := json.Marshal(mapValue)
_ = json.Unmarshal(b, obj)
return nil
}

func checkParam(of reflect.Value, obj interface{}, decoder *json.Decoder) error {
// 解析为map,然后根据map中的key 进行比对
// 判断类型 结构体 才能解析为map
mapValue := make(map[string]interface{})
_ = decoder.Decode(&mapValue)
for i := 0; i < of.NumField(); i++ {
field := of.Type().Field(i)
name := field.Name
jsonName := field.Tag.Get("json")
if jsonName != "" {
name = jsonName
}
required := field.Tag.Get("polevalidate")
value := mapValue[name]
if value == nil && required == "required" {
return errors.New(fmt.Sprintf("filed [%s] is not exist,because [%s] is required", jsonName, jsonName))
}
}
b, _ := json.Marshal(mapValue)
_ = json.Unmarshal(b, obj)
return nil
}
91 changes: 91 additions & 0 deletions binding/validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package binding

import (
"fmt"
"reflect"
"strings"
"sync"

"github.com/go-playground/validator/v10"
)

type StructValidator interface {
// 结构体验证,如果错误返回对应的错误信息
ValidateStruct(interface{}) error
// 返回对应使用的验证器
Engine() interface{}
}

var Validator StructValidator = &defaultValidator{}

type defaultValidator struct {
one sync.Once
validate *validator.Validate
}

type SliceValidationError []error

func (err SliceValidationError) Error() string {
n := len(err)
switch n {
case 0:
return ""
default:
var b strings.Builder
if err[0] != nil {
fmt.Fprintf(&b, "[%d]: %s", 0, err[0].Error())
}
if n > 1 {
for i := 1; i < n; i++ {
if err[i] != nil {
b.WriteString("\n")
fmt.Fprintf(&b, "[%d]: %s", i, err[i].Error())
}
}
}
return b.String()
}
}

func (d *defaultValidator) ValidateStruct(obj interface{}) error {
of := reflect.ValueOf(obj)
switch of.Kind() {
case reflect.Ptr:
return d.ValidateStruct(of.Elem().Interface())
case reflect.Struct:
return d.validateStruct(obj)
case reflect.Slice, reflect.Array:
count := of.Len()
sliceValidationError := make(SliceValidationError, 0)
for i := 0; i < count; i++ {
if err := d.validateStruct(of.Index(i).Interface()); err != nil {
sliceValidationError = append(sliceValidationError, err)
}
}
if len(sliceValidationError) == 0 {
return nil
}
return sliceValidationError
}
return nil
}

func (d *defaultValidator) Engine() interface{} {
d.lazyInit()
return d.validate
}

func (d *defaultValidator) lazyInit() {
d.one.Do(func() {
d.validate = validator.New()
})
}

func (d *defaultValidator) validateStruct(obj interface{}) error {
d.lazyInit()
return d.validate.Struct(obj)
}

func validate(obj interface{}) error {
return Validator.ValidateStruct(obj)
}
24 changes: 24 additions & 0 deletions binding/xml.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package binding

import (
"encoding/xml"
"net/http"
)

type xmlBinding struct {
}

func (xmlBinding) Name() string {
return "xml"
}

func (b xmlBinding) Bind(r *http.Request, obj interface{}) error {
if r.Body == nil {
return nil
}
decoder := xml.NewDecoder(r.Body)
if err := decoder.Decode(obj); err != nil {
return err
}
return validate(obj)
}
Loading

0 comments on commit 8677ee0

Please sign in to comment.