-
Notifications
You must be signed in to change notification settings - Fork 248
/
rewritejsontag.go
132 lines (124 loc) · 3.41 KB
/
rewritejsontag.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package astutils
import (
"bytes"
"fmt"
"github.com/pkg/errors"
"github.com/unionj-cloud/go-doudou/v2/toolkit/caller"
"go/ast"
"go/format"
"go/parser"
"go/token"
"golang.org/x/tools/go/ast/astutil"
"regexp"
"strings"
"unicode"
)
func isExport(field string) bool {
return unicode.IsUpper([]rune(field)[0])
}
func extractJsonPropName(tag string) string {
re := regexp.MustCompile(`json:"(.*?)"`)
if re.MatchString(tag) {
subs := re.FindAllStringSubmatch(tag, -1)
return strings.TrimSpace(strings.Split(subs[0][1], ",")[0])
}
return ""
}
func extractFormPropName(tag string) string {
re := regexp.MustCompile(`form:"(.*?)"`)
if re.MatchString(tag) {
subs := re.FindAllStringSubmatch(tag, -1)
return strings.TrimSpace(strings.Split(subs[0][1], ",")[0])
}
return ""
}
type RewriteTagConfig struct {
File string
Omitempty bool
ConvertFunc func(old string) string
Form bool
}
// RewriteTag overwrites json tag by convert function and return formatted source code
func RewriteTag(config RewriteTagConfig) (string, error) {
file, convert, omitempty, form := config.File, config.ConvertFunc, config.Omitempty, config.Form
fset := token.NewFileSet()
root, err := parser.ParseFile(fset, file, nil, parser.ParseComments)
if err != nil {
return "", errors.Wrap(err, caller.NewCaller().String())
}
re := regexp.MustCompile(`json:"(.*?)"`)
reForm := regexp.MustCompile(`form:"(.*?)"`)
astutil.Apply(root, func(cursor *astutil.Cursor) bool {
return true
}, func(cursor *astutil.Cursor) bool {
structSpec, ok := cursor.Node().(*ast.StructType)
if !ok {
return true
}
for _, field := range structSpec.Fields.List {
if field.Names == nil {
continue
}
fname := field.Names[0].Name
if !isExport(fname) {
continue
}
tagValue := convert(field.Names[0].Name)
jsonTagValue := tagValue
if omitempty {
jsonTagValue += ",omitempty"
}
jsonTag := fmt.Sprintf(`json:"%s"`, jsonTagValue)
formTagValue := tagValue
if omitempty {
formTagValue += ",omitempty"
}
formTag := fmt.Sprintf(`form:"%s"`, formTagValue)
if field.Tag != nil {
if re.MatchString(field.Tag.Value) {
if extractJsonPropName(field.Tag.Value) != "-" {
field.Tag.Value = re.ReplaceAllLiteralString(field.Tag.Value, jsonTag)
}
} else {
lastindex := strings.LastIndex(field.Tag.Value, "`")
if lastindex < 0 {
panic(errors.New("call LastIndex() error"))
}
field.Tag.Value = field.Tag.Value[:lastindex] + fmt.Sprintf(" %s`", jsonTag)
}
if form {
if reForm.MatchString(field.Tag.Value) {
if extractFormPropName(field.Tag.Value) != "-" {
field.Tag.Value = reForm.ReplaceAllLiteralString(field.Tag.Value, formTag)
}
} else {
lastindex := strings.LastIndex(field.Tag.Value, "`")
if lastindex < 0 {
panic(errors.New("call LastIndex() error"))
}
field.Tag.Value = field.Tag.Value[:lastindex] + fmt.Sprintf(" %s`", formTag)
}
}
} else {
if form {
field.Tag = &ast.BasicLit{
Kind: token.STRING,
Value: fmt.Sprintf("`%s %s`", jsonTag, formTag),
}
} else {
field.Tag = &ast.BasicLit{
Kind: token.STRING,
Value: fmt.Sprintf("`%s`", jsonTag),
}
}
}
}
return true
})
buf := &bytes.Buffer{}
err = format.Node(buf, fset, root)
if err != nil {
return "", fmt.Errorf("error formatting new code: %w", err)
}
return buf.String(), nil
}