1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package swag
16
17 import (
18 "bytes"
19 "encoding/json"
20 "log"
21 "reflect"
22 "strings"
23 "sync"
24
25 "github.com/mailru/easyjson/jlexer"
26 "github.com/mailru/easyjson/jwriter"
27 )
28
29
30 var nullJSON = []byte("null")
31
32
33 var DefaultJSONNameProvider = NewNameProvider()
34
35 const comma = byte(',')
36
37 var closers map[byte]byte
38
39 func init() {
40 closers = map[byte]byte{
41 '{': '}',
42 '[': ']',
43 }
44 }
45
46 type ejMarshaler interface {
47 MarshalEasyJSON(w *jwriter.Writer)
48 }
49
50 type ejUnmarshaler interface {
51 UnmarshalEasyJSON(w *jlexer.Lexer)
52 }
53
54
55
56 func WriteJSON(data interface{}) ([]byte, error) {
57 if d, ok := data.(ejMarshaler); ok {
58 jw := new(jwriter.Writer)
59 d.MarshalEasyJSON(jw)
60 return jw.BuildBytes()
61 }
62 if d, ok := data.(json.Marshaler); ok {
63 return d.MarshalJSON()
64 }
65 return json.Marshal(data)
66 }
67
68
69
70 func ReadJSON(data []byte, value interface{}) error {
71 trimmedData := bytes.Trim(data, "\x00")
72 if d, ok := value.(ejUnmarshaler); ok {
73 jl := &jlexer.Lexer{Data: trimmedData}
74 d.UnmarshalEasyJSON(jl)
75 return jl.Error()
76 }
77 if d, ok := value.(json.Unmarshaler); ok {
78 return d.UnmarshalJSON(trimmedData)
79 }
80 return json.Unmarshal(trimmedData, value)
81 }
82
83
84 func DynamicJSONToStruct(data interface{}, target interface{}) error {
85
86 b, err := WriteJSON(data)
87 if err != nil {
88 return err
89 }
90 return ReadJSON(b, target)
91 }
92
93
94 func ConcatJSON(blobs ...[]byte) []byte {
95 if len(blobs) == 0 {
96 return nil
97 }
98
99 last := len(blobs) - 1
100 for blobs[last] == nil || bytes.Equal(blobs[last], nullJSON) {
101
102 last--
103 if last < 0 {
104
105 return nil
106 }
107 }
108 if last == 0 {
109 return blobs[0]
110 }
111
112 var opening, closing byte
113 var idx, a int
114 buf := bytes.NewBuffer(nil)
115
116 for i, b := range blobs[:last+1] {
117 if b == nil || bytes.Equal(b, nullJSON) {
118
119 continue
120 }
121 if len(b) > 0 && opening == 0 {
122 opening, closing = b[0], closers[b[0]]
123 }
124
125 if opening != '{' && opening != '[' {
126 continue
127 }
128
129 if len(b) < 3 {
130 if i == last && a > 0 {
131 if err := buf.WriteByte(closing); err != nil {
132 log.Println(err)
133 }
134 }
135 continue
136 }
137
138 idx = 0
139 if a > 0 {
140 if err := buf.WriteByte(comma); err != nil {
141 log.Println(err)
142 }
143 idx = 1
144 }
145
146 if i != last {
147 if _, err := buf.Write(b[idx : len(b)-1]); err != nil {
148 log.Println(err)
149 }
150 } else {
151 if _, err := buf.Write(b[idx:]); err != nil {
152 log.Println(err)
153 }
154 }
155 a++
156 }
157
158 if buf.Len() == 0 {
159 if err := buf.WriteByte(opening); err != nil {
160 log.Println(err)
161 }
162 if err := buf.WriteByte(closing); err != nil {
163 log.Println(err)
164 }
165 }
166 return buf.Bytes()
167 }
168
169
170 func ToDynamicJSON(data interface{}) interface{} {
171
172 b, err := json.Marshal(data)
173 if err != nil {
174 log.Println(err)
175 }
176 var res interface{}
177 if err := json.Unmarshal(b, &res); err != nil {
178 log.Println(err)
179 }
180 return res
181 }
182
183
184 func FromDynamicJSON(data, target interface{}) error {
185 b, err := json.Marshal(data)
186 if err != nil {
187 log.Println(err)
188 }
189 return json.Unmarshal(b, target)
190 }
191
192
193
194
195 type NameProvider struct {
196 lock *sync.Mutex
197 index map[reflect.Type]nameIndex
198 }
199
200 type nameIndex struct {
201 jsonNames map[string]string
202 goNames map[string]string
203 }
204
205
206 func NewNameProvider() *NameProvider {
207 return &NameProvider{
208 lock: &sync.Mutex{},
209 index: make(map[reflect.Type]nameIndex),
210 }
211 }
212
213 func buildnameIndex(tpe reflect.Type, idx, reverseIdx map[string]string) {
214 for i := 0; i < tpe.NumField(); i++ {
215 targetDes := tpe.Field(i)
216
217 if targetDes.PkgPath != "" {
218 continue
219 }
220
221 if targetDes.Anonymous {
222 buildnameIndex(targetDes.Type, idx, reverseIdx)
223 continue
224 }
225
226 if tag := targetDes.Tag.Get("json"); tag != "" {
227
228 parts := strings.Split(tag, ",")
229 if len(parts) == 0 {
230 continue
231 }
232
233 nm := parts[0]
234 if nm == "-" {
235 continue
236 }
237 if nm == "" {
238 nm = targetDes.Name
239 }
240
241 idx[nm] = targetDes.Name
242 reverseIdx[targetDes.Name] = nm
243 }
244 }
245 }
246
247 func newNameIndex(tpe reflect.Type) nameIndex {
248 var idx = make(map[string]string, tpe.NumField())
249 var reverseIdx = make(map[string]string, tpe.NumField())
250
251 buildnameIndex(tpe, idx, reverseIdx)
252 return nameIndex{jsonNames: idx, goNames: reverseIdx}
253 }
254
255
256 func (n *NameProvider) GetJSONNames(subject interface{}) []string {
257 n.lock.Lock()
258 defer n.lock.Unlock()
259 tpe := reflect.Indirect(reflect.ValueOf(subject)).Type()
260 names, ok := n.index[tpe]
261 if !ok {
262 names = n.makeNameIndex(tpe)
263 }
264
265 res := make([]string, 0, len(names.jsonNames))
266 for k := range names.jsonNames {
267 res = append(res, k)
268 }
269 return res
270 }
271
272
273 func (n *NameProvider) GetJSONName(subject interface{}, name string) (string, bool) {
274 tpe := reflect.Indirect(reflect.ValueOf(subject)).Type()
275 return n.GetJSONNameForType(tpe, name)
276 }
277
278
279 func (n *NameProvider) GetJSONNameForType(tpe reflect.Type, name string) (string, bool) {
280 n.lock.Lock()
281 defer n.lock.Unlock()
282 names, ok := n.index[tpe]
283 if !ok {
284 names = n.makeNameIndex(tpe)
285 }
286 nme, ok := names.goNames[name]
287 return nme, ok
288 }
289
290 func (n *NameProvider) makeNameIndex(tpe reflect.Type) nameIndex {
291 names := newNameIndex(tpe)
292 n.index[tpe] = names
293 return names
294 }
295
296
297 func (n *NameProvider) GetGoName(subject interface{}, name string) (string, bool) {
298 tpe := reflect.Indirect(reflect.ValueOf(subject)).Type()
299 return n.GetGoNameForType(tpe, name)
300 }
301
302
303 func (n *NameProvider) GetGoNameForType(tpe reflect.Type, name string) (string, bool) {
304 n.lock.Lock()
305 defer n.lock.Unlock()
306 names, ok := n.index[tpe]
307 if !ok {
308 names = n.makeNameIndex(tpe)
309 }
310 nme, ok := names.jsonNames[name]
311 return nme, ok
312 }
313
View as plain text