-
Notifications
You must be signed in to change notification settings - Fork 94
/
plugins.go
161 lines (133 loc) · 3.61 KB
/
plugins.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package xml2json
import (
"strings"
)
type (
// an plugin is added to an encoder or/and to an decoder to allow custom functionality at runtime
plugin interface {
AddToEncoder(*Encoder) *Encoder
AddToDecoder(*Decoder) *Decoder
}
// a type converter overides the default string sanitization for encoding json
encoderTypeConverter interface {
Convert(string) string
}
// customTypeConverter converts strings to JSON types using a best guess approach, only parses the JSON types given
// when initialized via WithTypeConverter
customTypeConverter struct {
parseTypes []JSType
}
attrPrefixer string
contentPrefixer string
excluder []string
nodesFormatter struct {
list []nodeFormatter
}
nodeFormatter struct {
path string
plugin nodePlugin
}
nodePlugin interface {
AddTo(*Node)
}
arrayFormatter struct{}
)
// WithTypeConverter allows customized js type conversion behavior by passing in the desired JSTypes
func WithTypeConverter(ts ...JSType) *customTypeConverter {
return &customTypeConverter{parseTypes: ts}
}
func (tc *customTypeConverter) parseAsString(t JSType) bool {
if t == String {
return true
}
for i := 0; i < len(tc.parseTypes); i++ {
if tc.parseTypes[i] == t {
return false
}
}
return true
}
// Adds the type converter to the encoder
func (tc *customTypeConverter) AddToEncoder(e *Encoder) *Encoder {
e.tc = tc
return e
}
func (tc *customTypeConverter) AddToDecoder(d *Decoder) *Decoder {
return d
}
func (tc *customTypeConverter) Convert(s string) string {
// remove quotes if they exists
if strings.HasPrefix(s, `"`) && strings.HasSuffix(s, `"`) {
s = s[1 : len(s)-1]
}
jsType := Str2JSType(s)
if tc.parseAsString(jsType) {
// add the quotes removed at the start of this func
s = `"` + s + `"`
}
return s
}
// WithAttrPrefix appends the given prefix to the json output of xml attribute fields to preserve namespaces
func WithAttrPrefix(prefix string) *attrPrefixer {
ap := attrPrefixer(prefix)
return &ap
}
func (a *attrPrefixer) AddToEncoder(e *Encoder) *Encoder {
e.attributePrefix = string((*a))
return e
}
func (a *attrPrefixer) AddToDecoder(d *Decoder) *Decoder {
d.attributePrefix = string((*a))
return d
}
// WithContentPrefix appends the given prefix to the json output of xml content fields to preserve namespaces
func WithContentPrefix(prefix string) *contentPrefixer {
c := contentPrefixer(prefix)
return &c
}
func (c *contentPrefixer) AddToEncoder(e *Encoder) *Encoder {
e.contentPrefix = string((*c))
return e
}
func (c *contentPrefixer) AddToDecoder(d *Decoder) *Decoder {
d.contentPrefix = string((*c))
return d
}
// ExcludeAttributes excludes some xml attributes, for example, xmlns:xsi, xsi:noNamespaceSchemaLocation
func ExcludeAttributes(attrs []string) *excluder {
ex := excluder(attrs)
return &ex
}
func (ex *excluder) AddToEncoder(e *Encoder) *Encoder {
return e
}
func (ex *excluder) AddToDecoder(d *Decoder) *Decoder {
d.ExcludeAttributes([]string((*ex)))
return d
}
// WithNodes formats specific nodes
func WithNodes(n ...nodeFormatter) *nodesFormatter {
return &nodesFormatter{list: n}
}
func (nf *nodesFormatter) AddToEncoder(e *Encoder) *Encoder {
return e
}
func (nf *nodesFormatter) AddToDecoder(d *Decoder) *Decoder {
d.AddFormatters(nf.list)
return d
}
func NodePlugin(path string, plugin nodePlugin) nodeFormatter {
return nodeFormatter{path: path, plugin: plugin}
}
func (nf *nodeFormatter) Format(node *Node) {
child := node.GetChild(nf.path)
if child != nil {
nf.plugin.AddTo(child)
}
}
func ToArray() *arrayFormatter {
return &arrayFormatter{}
}
func (af *arrayFormatter) AddTo(n *Node) {
n.ChildrenAlwaysAsArray = true
}