[feat] 新增 Response GlobalParams 辅助对象
This commit is contained in:
parent
829dcc1d75
commit
f3d4de13b2
4
go.mod
4
go.mod
@ -12,6 +12,8 @@ require (
|
|||||||
github.com/samber/lo v1.38.1
|
github.com/samber/lo v1.38.1
|
||||||
github.com/spf13/cast v1.5.0
|
github.com/spf13/cast v1.5.0
|
||||||
github.com/spf13/viper v1.15.0
|
github.com/spf13/viper v1.15.0
|
||||||
|
github.com/tidwall/gjson v1.14.4
|
||||||
|
github.com/tidwall/sjson v1.2.5
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@ -34,6 +36,8 @@ require (
|
|||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/subosito/gotenv v1.4.2 // indirect
|
github.com/subosito/gotenv v1.4.2 // indirect
|
||||||
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
|
github.com/tidwall/pretty v1.2.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
|
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
|
||||||
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
|
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
|
||||||
golang.org/x/sys v0.3.0 // indirect
|
golang.org/x/sys v0.3.0 // indirect
|
||||||
|
9
go.sum
9
go.sum
@ -202,6 +202,15 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs
|
|||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
|
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
|
||||||
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||||
|
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
|
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
|
||||||
|
github.com/tidwall/gjson v1.14.4/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/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
|
||||||
|
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
228
support/global_params.go
Normal file
228
support/global_params.go
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
package support
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/samber/lo"
|
||||||
|
"github.com/spf13/cast"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
"github.com/tidwall/sjson"
|
||||||
|
|
||||||
|
"git.fsdpf.net/go/contracts"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GlobalParams struct {
|
||||||
|
user *contracts.User
|
||||||
|
gjson gjson.Result
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户信息
|
||||||
|
func (this GlobalParams) User() contracts.User {
|
||||||
|
return *this.user
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取指定路径的 value
|
||||||
|
func (this GlobalParams) Get(key string) contracts.GlobalParams {
|
||||||
|
return &GlobalParams{
|
||||||
|
user: this.user,
|
||||||
|
gjson: this.gjson.Get(key),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
func (this GlobalParams) Array() []contracts.GlobalParams {
|
||||||
|
return lo.Map(this.gjson.Array(), func(item gjson.Result, _ int) contracts.GlobalParams {
|
||||||
|
return &GlobalParams{user: this.user, gjson: gjson.Parse(item.Raw)}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取golang原始类型
|
||||||
|
func (this GlobalParams) Value() any {
|
||||||
|
return this.gjson.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this GlobalParams) Raw() string {
|
||||||
|
return this.gjson.Raw
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置json值
|
||||||
|
func (this *GlobalParams) Set(p string, v any) bool {
|
||||||
|
if s, err := sjson.Set(this.Raw(), p, v); err != nil {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
this.gjson = gjson.Parse(s)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置json原始值
|
||||||
|
func (this *GlobalParams) SetRaw(p, v string) bool {
|
||||||
|
if s, err := sjson.SetRaw(this.Raw(), p, v); err != nil {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
this.gjson = gjson.Parse(s)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除路径内容
|
||||||
|
func (this *GlobalParams) Delete(p string) bool {
|
||||||
|
if s, err := sjson.Delete(this.Raw(), p); err != nil {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
this.gjson = gjson.Parse(s)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 路径包裹
|
||||||
|
func (this *GlobalParams) Wrapped(p string) contracts.GlobalParams {
|
||||||
|
return this.AppendTo("", p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 包裹内容
|
||||||
|
func (this *GlobalParams) AppendTo(root, p string) contracts.GlobalParams {
|
||||||
|
if root != "" && !gjson.Valid(root) {
|
||||||
|
root = ""
|
||||||
|
}
|
||||||
|
return NewGlobalParam(lo.Must(sjson.SetRaw(root, p, this.Raw())), *this.user)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断值是否存在
|
||||||
|
func (this GlobalParams) Exists() bool {
|
||||||
|
return this.gjson.Exists()
|
||||||
|
}
|
||||||
|
|
||||||
|
// to Bool
|
||||||
|
func (this GlobalParams) Bool() bool {
|
||||||
|
return cast.ToBool(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to Time
|
||||||
|
func (this GlobalParams) Time() time.Time {
|
||||||
|
return cast.ToTime(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to Location Time
|
||||||
|
func (this GlobalParams) TimeInDefaultLocation(location *time.Location) time.Time {
|
||||||
|
return cast.ToTimeInDefaultLocation(this, location)
|
||||||
|
}
|
||||||
|
|
||||||
|
// to float64
|
||||||
|
func (this GlobalParams) Float64() float64 {
|
||||||
|
return cast.ToFloat64(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to float32
|
||||||
|
func (this GlobalParams) Float32() float32 {
|
||||||
|
return cast.ToFloat32(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to int64
|
||||||
|
func (this GlobalParams) Int64() int64 {
|
||||||
|
return cast.ToInt64(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to int32
|
||||||
|
func (this GlobalParams) Int32() int32 {
|
||||||
|
return cast.ToInt32(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to int16
|
||||||
|
func (this GlobalParams) Int16() int16 {
|
||||||
|
return cast.ToInt16(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to int8
|
||||||
|
func (this GlobalParams) Int8() int8 {
|
||||||
|
return cast.ToInt8(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to int
|
||||||
|
func (this GlobalParams) Int() int {
|
||||||
|
return cast.ToInt(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to uint
|
||||||
|
func (this GlobalParams) Uint() uint {
|
||||||
|
return cast.ToUint(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to uint64
|
||||||
|
func (this GlobalParams) Uint64() uint64 {
|
||||||
|
return cast.ToUint64(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to uint32
|
||||||
|
func (this GlobalParams) Uint32() uint32 {
|
||||||
|
return cast.ToUint32(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to uint16
|
||||||
|
func (this GlobalParams) Uint16() uint16 {
|
||||||
|
return cast.ToUint16(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to uint8
|
||||||
|
func (this GlobalParams) Uint8() uint8 {
|
||||||
|
return cast.ToUint8(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to string
|
||||||
|
func (this GlobalParams) String() string {
|
||||||
|
return cast.ToString(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to map[string]string
|
||||||
|
func (this GlobalParams) StringMapString() map[string]string {
|
||||||
|
return cast.ToStringMapString(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to map[string][]string
|
||||||
|
func (this GlobalParams) StringMapStringSlice() map[string][]string {
|
||||||
|
return cast.ToStringMapStringSlice(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to map[string]bool
|
||||||
|
func (this GlobalParams) StringMapBool() map[string]bool {
|
||||||
|
return cast.ToStringMapBool(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to map[string]int
|
||||||
|
func (this GlobalParams) StringMapInt() map[string]int {
|
||||||
|
return cast.ToStringMapInt(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to map[string]int64
|
||||||
|
func (this GlobalParams) StringMapInt64() map[string]int64 {
|
||||||
|
return cast.ToStringMapInt64(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to map[string]any
|
||||||
|
func (this GlobalParams) StringMap() map[string]any {
|
||||||
|
return cast.ToStringMap(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to []any
|
||||||
|
func (this GlobalParams) Slice() []any {
|
||||||
|
return cast.ToSlice(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to []bool
|
||||||
|
func (this GlobalParams) BoolSlice() []bool {
|
||||||
|
return cast.ToBoolSlice(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to []string
|
||||||
|
func (this GlobalParams) StringSlice() []string {
|
||||||
|
return cast.ToStringSlice(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
// to []int
|
||||||
|
func (this GlobalParams) IntSlice() []int {
|
||||||
|
return cast.ToIntSlice(this.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGlobalParam(data string, user contracts.User) contracts.GlobalParams {
|
||||||
|
return &GlobalParams{user: &user, gjson: gjson.Parse(data)}
|
||||||
|
}
|
205
support/response.go
Normal file
205
support/response.go
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
package support
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.fsdpf.net/go/contracts"
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
"github.com/samber/lo"
|
||||||
|
)
|
||||||
|
|
||||||
|
type JsonResponse struct {
|
||||||
|
raw []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type MsgResponse struct {
|
||||||
|
code int
|
||||||
|
msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ErrResponse struct {
|
||||||
|
*MsgResponse
|
||||||
|
stack []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileResponse struct {
|
||||||
|
disposition string
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
var wsUpgrader = websocket.Upgrader{
|
||||||
|
CheckOrigin: func(r *http.Request) bool {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this JsonResponse) Get(path ...string) contracts.GlobalParams {
|
||||||
|
return lo.Ternary(len(path) == 0, NewGlobalParam(string(this.raw), nil), NewGlobalParam(string(this.raw), nil).Get(strings.Join(path, ".")))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this JsonResponse) Send(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Header.Get("Upgrade") != "" && strings.ToLower(r.Header.Get("Upgrade")) == "websocket" {
|
||||||
|
c, _ := wsUpgrader.Upgrade(w, r, nil)
|
||||||
|
c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, string(this.raw)))
|
||||||
|
c.Close()
|
||||||
|
} else {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.Write(this.raw)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this MsgResponse) Get(path ...string) contracts.GlobalParams {
|
||||||
|
if resp, err := json.Marshal(map[string]any{
|
||||||
|
"code": this.code,
|
||||||
|
"msg": this.msg,
|
||||||
|
}); err == nil {
|
||||||
|
return lo.Ternary(len(path) == 0, NewGlobalParam(string(resp), nil), NewGlobalParam(string(resp), nil).Get(strings.Join(path, ".")))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this MsgResponse) Send(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if resp, err := json.Marshal(this.Get().Value()); err == nil {
|
||||||
|
(&JsonResponse{raw: resp}).Send(w, r)
|
||||||
|
} else {
|
||||||
|
HttpResponse(err).Send(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this ErrResponse) Get(path ...string) contracts.GlobalParams {
|
||||||
|
if resp, err := json.Marshal(map[string]any{
|
||||||
|
"code": this.code,
|
||||||
|
"msg": this.msg,
|
||||||
|
"error": string(this.stack),
|
||||||
|
}); err == nil {
|
||||||
|
return lo.Ternary(len(path) == 0, NewGlobalParam(string(resp), nil), NewGlobalParam(string(resp), nil).Get(strings.Join(path, ".")))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this ErrResponse) Send(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if resp, err := json.Marshal(this.Get().Value()); err == nil {
|
||||||
|
(&JsonResponse{raw: resp}).Send(w, r)
|
||||||
|
} else {
|
||||||
|
HttpResponse(err).Send(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this FileResponse) Get(path ...string) contracts.GlobalParams {
|
||||||
|
if resp, err := json.Marshal(map[string]any{
|
||||||
|
"name": this.name,
|
||||||
|
"disposition": this.disposition,
|
||||||
|
}); err == nil {
|
||||||
|
return lo.Ternary(len(path) == 0, NewGlobalParam(string(resp), nil), NewGlobalParam(string(resp), nil).Get(strings.Join(path, ".")))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this FileResponse) Send(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if this.Get("disposition").String() != "" {
|
||||||
|
w.Header().Set("Content-Disposition", `attachment; filename="`+this.Get("disposition").String()+`"`)
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(this.Get("name").String()); err != nil && os.IsNotExist(err) {
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
} else {
|
||||||
|
http.ServeFile(w, r, this.Get("name").String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewJsonResponse(b []byte) contracts.HttpResponse {
|
||||||
|
return &JsonResponse{raw: b}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFileResponse(name string, disposition string) contracts.HttpResponse {
|
||||||
|
return &FileResponse{name: name, disposition: disposition}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMsgResponse(msg string, code int) contracts.HttpResponse {
|
||||||
|
return &MsgResponse{msg: msg, code: code}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewErrResponse(p ...any) contracts.HttpResponse {
|
||||||
|
code := contracts.InternalServerError.Code
|
||||||
|
msg := contracts.InternalServerError.Error()
|
||||||
|
data := any(nil)
|
||||||
|
|
||||||
|
for i := 0; i < len(p); i++ {
|
||||||
|
switch v := p[i].(type) {
|
||||||
|
case error:
|
||||||
|
msg = v.Error()
|
||||||
|
case string:
|
||||||
|
msg = v
|
||||||
|
case int:
|
||||||
|
code = v
|
||||||
|
case contracts.Errno:
|
||||||
|
msg = v.Error()
|
||||||
|
code = v.Code
|
||||||
|
case *contracts.Errno:
|
||||||
|
msg = v.Error()
|
||||||
|
code = v.Code
|
||||||
|
default:
|
||||||
|
data = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stackBuf := make([]byte, 1024)
|
||||||
|
n := runtime.Stack(stackBuf[:], false)
|
||||||
|
|
||||||
|
b, _ := json.Marshal(struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
Data any `json:"data,omitempty"`
|
||||||
|
Stack string `json:"stack"`
|
||||||
|
}{
|
||||||
|
Code: code,
|
||||||
|
Msg: msg,
|
||||||
|
Data: data,
|
||||||
|
Stack: string(stackBuf[:n]),
|
||||||
|
})
|
||||||
|
|
||||||
|
return NewJsonResponse(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HttpResponse(data any) contracts.HttpResponse {
|
||||||
|
var err error = contracts.InternalServerError
|
||||||
|
|
||||||
|
switch v := data.(type) {
|
||||||
|
case contracts.HttpResponse:
|
||||||
|
return v
|
||||||
|
case contracts.Errno:
|
||||||
|
return NewMsgResponse(v.Error(), v.Code)
|
||||||
|
case *contracts.Errno:
|
||||||
|
return NewMsgResponse(v.Error(), v.Code)
|
||||||
|
case error:
|
||||||
|
err = v
|
||||||
|
case []byte:
|
||||||
|
if b, e := json.Marshal(map[string]any{
|
||||||
|
"code": contracts.OK.Code,
|
||||||
|
"msg": contracts.OK.Msg,
|
||||||
|
"data": json.RawMessage(v),
|
||||||
|
}); e == nil {
|
||||||
|
return &JsonResponse{raw: b}
|
||||||
|
} else {
|
||||||
|
err = e
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if b, e := json.Marshal(map[string]any{
|
||||||
|
"code": contracts.OK.Code,
|
||||||
|
"msg": contracts.OK.Msg,
|
||||||
|
"data": v,
|
||||||
|
}); e == nil {
|
||||||
|
return &JsonResponse{raw: b}
|
||||||
|
} else {
|
||||||
|
err = e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewMsgResponse(err.Error(), contracts.InternalServerError.Code)
|
||||||
|
}
|
@ -5,6 +5,8 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/spf13/cast"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetFieldValue(i any, k string) any {
|
func GetFieldValue(i any, k string) any {
|
||||||
@ -42,6 +44,20 @@ func GetFieldValue(i any, k string) any {
|
|||||||
return kv.Interface()
|
return kv.Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetStructField(item any, key string) (field reflect.StructField, ok bool) {
|
||||||
|
vItem := reflect.TypeOf(item)
|
||||||
|
|
||||||
|
if vItem.Kind() == reflect.Ptr {
|
||||||
|
vItem = vItem.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
if vItem.Kind() != reflect.Struct {
|
||||||
|
return field, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return vItem.FieldByName(UcFirst(key))
|
||||||
|
}
|
||||||
|
|
||||||
func InterfaceToSlice(i any) (ret []any) {
|
func InterfaceToSlice(i any) (ret []any) {
|
||||||
rv := reflect.ValueOf(i)
|
rv := reflect.ValueOf(i)
|
||||||
|
|
||||||
@ -87,6 +103,54 @@ func SliceConvert(origSlice any, newSliceType reflect.Type) any {
|
|||||||
return newSlice.Elem().Interface()
|
return newSlice.Elem().Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DeepSearch(m map[string]any, path []string) map[string]any {
|
||||||
|
for _, k := range path {
|
||||||
|
m2, ok := m[k]
|
||||||
|
if !ok {
|
||||||
|
// intermediate key does not exist
|
||||||
|
// => create it and continue from there
|
||||||
|
m3 := make(map[string]interface{})
|
||||||
|
m[k] = m3
|
||||||
|
m = m3
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
m3, ok := m2.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
// intermediate key is a value
|
||||||
|
// => replace with a new map
|
||||||
|
m3 = make(map[string]interface{})
|
||||||
|
m[k] = m3
|
||||||
|
}
|
||||||
|
// continue search from here
|
||||||
|
m = m3
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func MergeMap(shadow map[string]any, m map[string]any) map[string]any {
|
||||||
|
if shadow == nil {
|
||||||
|
shadow = make(map[string]any)
|
||||||
|
}
|
||||||
|
|
||||||
|
var m2 map[string]any
|
||||||
|
|
||||||
|
for k, val := range m {
|
||||||
|
switch val.(type) {
|
||||||
|
case map[string]any:
|
||||||
|
m2 = val.(map[string]any)
|
||||||
|
case map[any]any:
|
||||||
|
m2 = cast.ToStringMap(val)
|
||||||
|
default:
|
||||||
|
// immediate value
|
||||||
|
shadow[k] = val
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// recursively merge to shadow map
|
||||||
|
shadow[k] = MergeMap(cast.ToStringMap(shadow[k]), m2)
|
||||||
|
}
|
||||||
|
return shadow
|
||||||
|
}
|
||||||
|
|
||||||
func UcFirst(s string) string {
|
func UcFirst(s string) string {
|
||||||
if s == "" {
|
if s == "" {
|
||||||
return ""
|
return ""
|
||||||
|
46
support/utils_test.go
Normal file
46
support/utils_test.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package support
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDeepSearch(t *testing.T) {
|
||||||
|
m := map[string]any{
|
||||||
|
"a": 1,
|
||||||
|
"b": map[string]any{
|
||||||
|
"c": 2,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
mb := DeepSearch(m, []string{"b", "a"})
|
||||||
|
|
||||||
|
t.Log(m)
|
||||||
|
|
||||||
|
mb["cc"] = "3"
|
||||||
|
|
||||||
|
t.Log(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeMap(t *testing.T) {
|
||||||
|
m1 := map[string]any{
|
||||||
|
"a": 1,
|
||||||
|
"b": map[string]any{
|
||||||
|
"c": 2,
|
||||||
|
"a": 1,
|
||||||
|
"b": map[string]any{
|
||||||
|
"c": 2,
|
||||||
|
"a": 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
m2 := map[string]any{
|
||||||
|
"a": 11,
|
||||||
|
"b": map[string]any{
|
||||||
|
"c": 22,
|
||||||
|
"cc": 33,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log(MergeMap(m1, m2))
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user