18 Commits

11 changed files with 668 additions and 1 deletions

42
cmd/define.go Normal file
View File

@ -0,0 +1,42 @@
// Package cmd...
//
// Description : cmd...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-12 2:18 下午
package cmd
// Config 配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:19 下午 2021/11/12
type Config struct {
WorkDir string `json:"work_dir"` // 工作目录
Command string `json:"command"` // 指令
Script string `json:"script"` // 脚本
ParameterList []Parameter `json:"parameter_list"` // 参数列表
}
// Parameter ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:21 下午 2021/11/12
type Parameter struct {
Key string `json:"key"`
Value string `json:"value"`
}
// Result ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 4:25 下午 2021/11/12
type Result struct {
WorkDir string `json:"work_dir"`
Err error `json:"err"`
Output []byte `json:"output"`
ExecuteCommand string `json:"execute_command"`
}

58
cmd/execute.go Normal file
View File

@ -0,0 +1,58 @@
// Package cmd...
//
// Description : cmd...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-12 2:21 下午
package cmd
import (
"os/exec"
"strings"
"git.zhangdeman.cn/zhangdeman/gopkg/util"
)
// Execute 执行指令
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:22 下午 2021/11/12
func Execute(cmdConfig Config) *Result {
if len(cmdConfig.WorkDir) == 0 {
cmdConfig.WorkDir, _ = util.GetProjectPath()
}
paramList := buildCmdParameter(cmdConfig.Script, cmdConfig.ParameterList)
cmdInstance := exec.Command(cmdConfig.Command, paramList...)
// 设置指令的工作目录
cmdInstance.Dir = cmdConfig.WorkDir
result := &Result{
Err: nil,
Output: nil,
WorkDir: cmdConfig.WorkDir,
ExecuteCommand: cmdConfig.Command + " " + strings.Join(paramList, " "),
}
result.Output, result.Err = cmdInstance.CombinedOutput()
return result
}
// buildCmdParameter 构建参数列表
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:53 下午 2021/11/12
func buildCmdParameter(script string, parameterList []Parameter) []string {
paramList := make([]string, 0)
if len(script) > 0 {
paramList = append(paramList, script)
}
for _, item := range parameterList {
if len(item.Key) == 0 {
paramList = append(paramList, item.Value)
continue
}
paramList = append(paramList, item.Key+"="+item.Value)
}
return paramList
}

17
git_hook/abstract.go Normal file
View File

@ -0,0 +1,17 @@
// Package git_hook...
//
// Description : git_hook...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-11 6:41 下午
package git_hook
import "github.com/gin-gonic/gin"
// IGitHookEventHandler 接口约束, pkg 内部会提供基础实现
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 6:42 下午 2021/11/11
type IGitHookEventHandler func(ctx *gin.Context, hookData *HookData) *ResponseData

165
git_hook/define.go Normal file
View File

@ -0,0 +1,165 @@
// Package git_hook...
//
// Description : git_hook...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-11 6:23 下午
package git_hook
// HookData hook通知数据
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 6:23 下午 2021/11/11
type HookData struct {
Repository Repository `json:"repository"` // 仓库信息
Sender User `json:"sender"`
Ref string `json:"ref"` // 分支,如 : refs/heads/master
Before string `json:"before"` // 之前版本号 : e162757f3f4a37786b4118a5346baae5dd24ecde
After string `json:"after"` // 当前版本号 : c70a362d850a820704bd374363ea4e7ea810fd1a
HeadCommit Commit `json:"head_commit"` // 最近一次提交
CompareUrl string `json:"compare_url"` // 两个版本号代码diff的URL, 点击后可查看diff
Commits []Commit `json:"commits"` // 提交记录列表
Pusher User `json:"pusher"` // 推送人信息
}
// Repository 仓库信息
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 6:24 下午 2021/11/11
type Repository struct {
Mirror bool `json:"mirror"`
OriginalUrl string `json:"original_url"` // original_url
StarsCount int64 `json:"stars_count"` // start 数量
IgnoreWhitespaceConflicts bool `json:"ignore_whitespace_conflicts"` // 忽略空格的冲突
FullName string `json:"full_name"` // 仓库完整名称
Fork bool `json:"fork"` // 是否 fork
CreatedAt string `json:"created_at"` // 创建时间
Internal bool `json:"internal"` // 是否内部仓库
AllowRebaseExplicit bool `json:"allow_rebase_explicit"` // 是否允许rebase
MirrorInterval string `json:"mirror_interval"` // mirror_interval
CloneUrl string `json:"clone_url"` // gi clone 对用的 https 地址
WatchersCount int64 `json:"watchers_count"` // 监听器数量
OpenIssuesCount int64 `json:"open_issues_count"` // 未解决的issues数量
ReleaseCounter int64 `json:"release_counter"` // 发布版本数量
InternalTracker RepositoryInternalTracker `json:"internal_tracker"` // 内部跟踪配置
Name string `json:"name"` // 仓库名称
Empty bool `json:"empty"` // 仓库是否为空
SshUrl string `json:"ssh_url"` // git clone 对应的 ssh 地址
ForksCount int64 `json:"forks_count"` // fork 次数
Permissions RepositoryPermission `json:"permissions"` // 权限配置
Private bool `json:"private"` // 是否为私有仓库
Size int64 `json:"size"` // 仓库大小 KB
HasWiki bool `json:"has_wiki"` // 是否有 wiki
HasProjects bool `json:"has_projects"` // 是否有项目
AllowMergeCommits bool `json:"allow_merge_commits"` // 是否允许合并提交
AvatarUrl string `json:"avatar_url"` // 头像地址
ID int64 `json:"id"` // 仓库ID
Description string `json:"description"` // 创建仓库时候的描述
Website string `json:"website"` // 网站
UpdatedAt string `json:"updated_at"` // 更新时间
HasPullRequests bool `json:"has_pull_requests"` // 是否有 pull request
Parent map[string]interface{} `json:"parent"` // parent
OpenPrCounter int64 `json:"open_pr_counter"` // 打开的pr数量
HasIssues bool `json:"has_issues"` // 是否有issues
AllowRebase bool `json:"allow_rebase"` // 是否允许rebase
AllowSquashMerge bool `json:"allow_squash_merge"` // 是否允许 合并 merge (将分支内容合并成一次提交, 合入主干)
Owner User `json:"owner"` // 仓库所有者信息
Template bool `json:"template"` // 是否是模版
HtmlUrl string `json:"html_url"` // 访问仓库的html地址
DefaultBranch string `json:"default_branch"` // 默认分支
Archived bool `json:"archived"` // 是否已归档
DefaultMergeStyle string `json:"default_merge_style"` // 默认的合并方式
}
// RepositoryInternalTracker 内部跟踪器
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 6:28 下午 2021/11/11
type RepositoryInternalTracker struct {
EnableTimeTracker bool `json:"enable_time_tracker"` // 启用time_tracker
AllowOnlyContributorsToTrackTime bool `json:"allow_only_contributors_to_track_time"` // 仅有代码贡献者允许
EnableIssueDependencies bool `json:"enable_issue_dependencies"` // 启用 issue_dependencies
}
// RepositoryPermission 仓库权限
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 6:29 下午 2021/11/11
type RepositoryPermission struct {
Pull bool `json:"pull"` // 是否允许 pull 代码
Admin bool `json:"admin"` // 是否是管理员
Push bool `json:"push"` // 是否允许push代码
}
// User 用户信息
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 6:30 下午 2021/11/11
type User struct {
IsAdmin bool `json:"is_admin"` // 是否是管理员
Website string `json:"website"` // 网页
Email string `json:"email"` // 邮箱
AvatarUrl string `json:"avatar_url"` // 头像
ProhibitLogin bool `json:"prohibit_login"` // 禁止登录
Description string `json:"description"` // 描述
FollowingCount int64 `json:"following_count"` // follower数量
StarredReposCount int64 `json:"starred_repos_count"` // star仓库数量
Username string `json:"username"` // 用户名
Login string `json:"login"` // 登录
Created string `json:"created"` // 创建时间
Visibility string `json:"visibility"` // 是否可见
FullName string `json:"full_name"` // 全名
LastLogin string `json:"last_login"` // 最近登录时间
Restricted bool `json:"restricted"` // 是否受限
Active bool `json:"active"` // 是否活跃
Location string `json:"location"` // 位置
FollowersCount int64 `json:"followers_count"` // follower数量
ID int64 `json:"id"` // id
Language string `json:"language"` // 语言
}
// Commit 提交记录信息
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 6:25 下午 2021/11/11
type Commit struct {
Message string `json:"message"` // 提交时带的message
Url string `json:"url"` // 浏览此版本代码的地址
Author CommitAuthor `json:"author"` // 作者信息
Verification map[string]interface{} `json:"verification"` // 验证
Timestamp string `json:"timestamp"` // 时间
ID string `json:"id"` // 提交的版本号 98ccd35d19d17c8e624a492cc5811fe6f381ca09
Committer CommitAuthor `json:"committer"` // 提交人信息
Added []string `json:"added"` // 增加的文件列表
Removed []string `json:"removed"` // 移除文件列表
Modified []string `json:"modified"` // 修改的文件列表
}
// CommitAuthor 提交人的信息
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 6:31 下午 2021/11/11
type CommitAuthor struct {
Name string `json:"name"` // 昵称
Email string `json:"email"` // 邮箱
Username string `json:"username"` // 用户名
}
// ResponseData 处理结果的返回值
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:37 上午 2021/11/12
type ResponseData struct {
Code interface{} `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}

45
git_hook/register.go Normal file
View File

@ -0,0 +1,45 @@
// Package git_hook...
//
// Description : git_hook...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-11 6:39 下午
package git_hook
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
)
// RegisterGitHookRouter 注册 git hook 回调的路由
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 6:40 下午 2021/11/11
func RegisterGitHookRouter(router *gin.Engine, handler IGitHookEventHandler) error {
if nil == handler {
return errors.New("handler is nil")
}
router.POST("/git/hook/notice", func(ctx *gin.Context) {
var (
hookData HookData
err error
)
if err = ctx.ShouldBindJSON(&hookData); nil != err {
ctx.JSON(http.StatusBadRequest, gin.H{"code": -1, "message": err.Error()})
}
responseData := handler(ctx, &hookData)
if nil == responseData {
responseData = &ResponseData{
Code: 100,
Message: "处理完成(未设置返回值,系统默认返回此信息)",
Data: map[string]interface{}{},
}
}
ctx.JSON(http.StatusOK, responseData)
})
return nil
}

3
go.mod
View File

@ -38,6 +38,7 @@ require (
github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.3 // indirect github.com/golang/snappy v0.0.3 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/hashicorp/go-uuid v1.0.2 // indirect github.com/hashicorp/go-uuid v1.0.2 // indirect
github.com/jcmturner/aescts/v2 v2.0.0 // indirect github.com/jcmturner/aescts/v2 v2.0.0 // indirect
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
@ -66,7 +67,7 @@ require (
go.uber.org/multierr v1.6.0 // indirect go.uber.org/multierr v1.6.0 // indirect
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e // indirect golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e // indirect
golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71 // indirect golang.org/x/sys v0.0.0-20211103235746-7861aae1554b // indirect
google.golang.org/protobuf v1.26.0 // indirect google.golang.org/protobuf v1.26.0 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect

7
go.sum
View File

@ -73,6 +73,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
@ -190,6 +192,8 @@ golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -228,6 +232,8 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71 h1:ikCpsnYR+Ew0vu99XlDp55lGgDJdIMx3f4a18jfse/s= golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71 h1:ikCpsnYR+Ew0vu99XlDp55lGgDJdIMx3f4a18jfse/s=
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@ -237,6 +243,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

185
tool/json2go/parser.go Normal file
View File

@ -0,0 +1,185 @@
// Package json2go ...
//
// Description : json2go ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-09 3:44 下午
package json2go
import (
"fmt"
"strings"
"git.zhangdeman.cn/zhangdeman/gopkg/util"
"github.com/pkg/errors"
"github.com/tidwall/gjson"
)
var (
// structName 结构体名称
structName = "Automatic"
)
// NewJSON2GO ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 6:13 下午 2021/11/9
func NewJSON2GO(name string) *JSON2GO {
if len(name) == 0 {
name = structName
}
return &JSON2GO{
structName: name,
}
}
// JSON2GO ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 6:12 下午 2021/11/9
type JSON2GO struct {
structName string
result string
}
// Parse ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:44 下午 2021/11/9
func (jg *JSON2GO) Parse(inputJSON string) (string, error) {
if !gjson.Valid(inputJSON) {
return "", errors.New("input json is invalid")
}
parseResult := gjson.Parse(inputJSON)
if parseResult.IsArray() {
jg.append("type " + jg.structName + " [] \n")
jg.parseArray("", parseResult)
} else {
jg.append("type " + jg.structName + " struct { \n")
jg.parseObject("", parseResult)
}
jg.append("}")
return jg.result, nil
}
// parseArray 解析array
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 4:37 下午 2021/11/9
func (jg *JSON2GO) parseArray(key string, parseResult gjson.Result) {
// 先遍历一遍确认所有数据类型都相同
dataType := ""
if len(parseResult.Array()) > 0 {
for _, item := range parseResult.Array() {
if len(dataType) == 0 {
dataType = jg.getDataType(item)
continue
}
currentType := jg.getDataType(item)
if currentType != dataType {
if (dataType == "int64" && currentType == "float64") || (dataType == "float64" && currentType == "int64") {
dataType = "float64"
continue
}
// 不是所有数据类型都一致
if len(key) == 0 {
jg.result += "interface{}"
return
}
jg.append(jg.buildField("[]interface{}", key))
return
}
}
} else {
dataType = "interface{}"
}
// 对象,重新
if dataType == "object" {
instance := NewJSON2GO("")
r, _ := instance.Parse(parseResult.Array()[0].String())
dataType = strings.Replace(strings.Replace(r, "type", "", 1), "Automatic", "", 1)
}
// 所有数据类型都一致
if len(key) == 0 {
jg.append("[]" + dataType)
} else {
jg.append(jg.buildField("[]"+dataType, key))
}
}
// parseObject 解析object
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 4:37 下午 2021/11/9
func (jg *JSON2GO) parseObject(key string, parseResult gjson.Result) string {
if len(key) > 0 {
jg.result += util.SnakeCaseToCamel(key) + " struct { \n"
}
for k, v := range parseResult.Map() {
if v.IsObject() {
jg.parseObject(k, v)
} else if v.IsArray() {
jg.parseArray(k, v)
} else {
jg.append(jg.buildField(jg.getDataType(v), k))
}
}
if len(key) > 0 {
jg.append(" } `json:\"" + key + "\"`\n")
}
return ""
}
// getDataType 获取数据类型
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:14 下午 2021/11/9
func (jg *JSON2GO) getDataType(val gjson.Result) string {
switch val.Type {
case gjson.True:
fallthrough
case gjson.False:
return "bool"
case gjson.Null:
return "map[string]interface{}"
case gjson.String:
return "string"
case gjson.Number:
tmpVal := fmt.Sprintf("%v", val.Num)
if strings.Contains(tmpVal, ".") {
return "float64"
}
return "int64"
case gjson.JSON:
return "object"
default:
return "interface{}"
}
}
// buildField 构建字段
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 9:20 下午 2021/11/9
func (jq *JSON2GO) buildField(fieldType string, jsonTag string) string {
return util.SnakeCaseToCamel(jsonTag) + " " + fieldType + " `json:\"" + jsonTag + "\"`\n"
}
// append 构建result
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 9:19 下午 2021/11/9
func (jq *JSON2GO) append(appendStr string) {
jq.result += appendStr
}

View File

@ -10,7 +10,10 @@ package util
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"os"
"reflect"
) )
// JSONUnmarshalWithNumber 解析json // JSONUnmarshalWithNumber 解析json
@ -34,3 +37,55 @@ func JSONUnmarshalWithNumberForIOReader(ioReader io.ReadCloser, receiver interfa
decoder.UseNumber() decoder.UseNumber()
return decoder.Decode(receiver) return decoder.Decode(receiver)
} }
// JSONConsoleOutput ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 5:45 下午 2021/11/5
func JSONConsoleOutput(data interface{}) {
var out bytes.Buffer
switch reflect.TypeOf(data).Kind() {
case reflect.Slice:
fallthrough
case reflect.Array:
fallthrough
case reflect.Map:
fallthrough
case reflect.Ptr:
byteData, _ := json.Marshal(data)
_ = json.Indent(&out, []byte(string(byteData)+"\n"), "", "\t")
_, _ = out.WriteTo(os.Stdout)
return
case reflect.Int:
fallthrough
case reflect.Int8:
fallthrough
case reflect.Int16:
fallthrough
case reflect.Int32:
fallthrough
case reflect.Int64:
fallthrough
case reflect.Uint:
fallthrough
case reflect.Uint8:
fallthrough
case reflect.Uint16:
fallthrough
case reflect.Uint32:
fallthrough
case reflect.Uint64:
fallthrough
case reflect.Float32:
fallthrough
case reflect.Float64:
fallthrough
case reflect.String:
_ = json.Indent(&out, []byte(fmt.Sprintf("%v\n", data)), "", "\t")
_, _ = out.WriteTo(os.Stdout)
return
default:
fmt.Println("")
}
}

View File

@ -54,6 +54,9 @@ func Md5(str string) string {
// //
// Date : 4:58 下午 2021/10/25 // Date : 4:58 下午 2021/10/25
func SnakeCaseToCamel(str string) string { func SnakeCaseToCamel(str string) string {
if len(str) == 0 {
return ""
}
builder := strings.Builder{} builder := strings.Builder{}
index := 0 index := 0
if str[0] >= 'a' && str[0] <= 'z' { if str[0] >= 'a' && str[0] <= 'z' {

89
util/url.go Normal file
View File

@ -0,0 +1,89 @@
// Package util...
//
// Description : util...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-04 2:38 下午
package util
import (
"net/url"
"strings"
)
// URLParseResult url解析
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:51 下午 2021/11/4
type URLParseResult struct {
Scheme string `json:"scheme"`
Domain string `json:"domain"`
URI string `json:"uri"`
Parameter map[string]string `json:"parameter"`
}
// URLEncode ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:39 下午 2021/11/4
func URLEncode(inputURL string) string {
return url.QueryEscape(inputURL)
}
// URLDecode ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:39 下午 2021/11/4
func URLDecode(inputURL string) (string, error) {
return url.QueryUnescape(inputURL)
}
// URLParse url解析
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:39 下午 2021/11/4
func URLParse(inputURL string) (*URLParseResult, error) {
var (
parseResult *url.URL
err error
)
if parseResult, err = url.Parse(inputURL); nil != err {
return nil, err
}
detail := &URLParseResult{
Scheme: parseResult.Scheme,
Domain: parseResult.Host,
URI: parseResult.Path,
Parameter: make(map[string]string),
}
for k, v := range parseResult.Query() {
if len(v) > 1 {
detail.Parameter[k] = "[" + strings.Join(v, ",") + "]"
} else {
detail.Parameter[k] = v[0]
}
}
return detail, nil
}
// BuildQueryURL 构建GET链接
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:43 下午 2021/11/4
func BuildQueryURL(apiURL string, parameter map[string]string) string {
u := url.Values{}
for k, v := range parameter {
u.Set(k, v)
}
apiURL = strings.Trim(apiURL, "?")
if strings.Contains(apiURL, "?") {
return apiURL + "&" + u.Encode()
}
return apiURL + "?" + u.Encode()
}