1 package json
2
3 import (
4 "fmt"
5 "math/big"
6 "reflect"
7
8 "github.com/aws/smithy-go/document"
9 "github.com/aws/smithy-go/document/internal/serde"
10 smithyjson "github.com/aws/smithy-go/encoding/json"
11 )
12
13
14 type EncoderOptions struct{}
15
16
17 type Encoder struct {
18 options EncoderOptions
19 }
20
21
22 func (e *Encoder) Encode(v interface{}) ([]byte, error) {
23 encoder := smithyjson.NewEncoder()
24
25 if err := e.encode(jsonValueProvider(encoder.Value), reflect.ValueOf(v), serde.Tag{}); err != nil {
26 return nil, err
27 }
28
29 encodedBytes := encoder.Bytes()
30
31 if len(encodedBytes) == 0 {
32 return nil, nil
33 }
34
35 return encodedBytes, nil
36 }
37
38
39 type valueProvider interface {
40 GetValue() smithyjson.Value
41 }
42
43
44 type jsonValueProvider smithyjson.Value
45
46 func (p jsonValueProvider) GetValue() smithyjson.Value {
47 return smithyjson.Value(p)
48 }
49
50
51
52 type jsonObjectKeyProvider struct {
53 Object *smithyjson.Object
54 Key string
55 }
56
57 func (p jsonObjectKeyProvider) GetValue() smithyjson.Value {
58 return p.Object.Key(p.Key)
59 }
60
61
62 type jsonArrayProvider struct {
63 Array *smithyjson.Array
64 }
65
66 func (p jsonArrayProvider) GetValue() smithyjson.Value {
67 return p.Array.Value()
68 }
69
70 func (e *Encoder) encode(vp valueProvider, rv reflect.Value, tag serde.Tag) error {
71
72 if serde.IsZeroValue(rv) {
73 if tag.OmitEmpty {
74 return nil
75 }
76 return e.encodeZeroValue(vp, rv)
77 }
78
79
80 rv = serde.ValueElem(rv)
81
82 switch rv.Kind() {
83 case reflect.Invalid:
84 if tag.OmitEmpty {
85 return nil
86 }
87 vp.GetValue().Null()
88 return nil
89
90 case reflect.Struct:
91 return e.encodeStruct(vp, rv)
92
93 case reflect.Map:
94 return e.encodeMap(vp, rv)
95
96 case reflect.Slice, reflect.Array:
97 return e.encodeSlice(vp, rv)
98
99 case reflect.Chan, reflect.Func, reflect.UnsafePointer:
100
101 return nil
102
103 default:
104 return e.encodeScalar(vp, rv)
105 }
106 }
107
108 func (e *Encoder) encodeZeroValue(vp valueProvider, rv reflect.Value) error {
109 switch rv.Kind() {
110 case reflect.Invalid:
111 vp.GetValue().Null()
112 case reflect.Array:
113 vp.GetValue().Array().Close()
114 case reflect.Map, reflect.Slice:
115 vp.GetValue().Null()
116 case reflect.String:
117 vp.GetValue().String("")
118 case reflect.Bool:
119 vp.GetValue().Boolean(false)
120 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
121 vp.GetValue().Long(0)
122 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
123 vp.GetValue().ULong(0)
124 case reflect.Float32, reflect.Float64:
125 vp.GetValue().Double(0)
126 case reflect.Interface, reflect.Ptr:
127 vp.GetValue().Null()
128 default:
129 return &document.InvalidMarshalError{Message: fmt.Sprintf("unknown value type: %s", rv.String())}
130 }
131
132 return nil
133 }
134
135 func (e *Encoder) encodeStruct(vp valueProvider, rv reflect.Value) error {
136 if rv.CanInterface() && document.IsNoSerde(rv.Interface()) {
137 return &document.UnmarshalTypeError{
138 Value: fmt.Sprintf("unsupported type"),
139 Type: rv.Type(),
140 }
141 }
142
143 switch {
144 case rv.Type().ConvertibleTo(serde.ReflectTypeOf.Time):
145 return &document.InvalidMarshalError{
146 Message: fmt.Sprintf("unsupported type %s", rv.Type().String()),
147 }
148 case rv.Type().ConvertibleTo(serde.ReflectTypeOf.BigFloat):
149 fallthrough
150 case rv.Type().ConvertibleTo(serde.ReflectTypeOf.BigInt):
151 return e.encodeNumber(vp, rv)
152 }
153
154 object := vp.GetValue().Object()
155 defer object.Close()
156
157 fields := serde.GetStructFields(rv.Type())
158 for _, f := range fields.All() {
159 if f.Name == "" {
160 return &document.InvalidMarshalError{Message: "map key cannot be empty"}
161 }
162
163 fv, found := serde.EncoderFieldByIndex(rv, f.Index)
164 if !found {
165 continue
166 }
167
168 err := e.encode(jsonObjectKeyProvider{
169 Object: object,
170 Key: f.Name,
171 }, fv, f.Tag)
172 if err != nil {
173 return err
174 }
175 }
176
177 return nil
178 }
179
180 func (e *Encoder) encodeMap(vp valueProvider, rv reflect.Value) error {
181 object := vp.GetValue().Object()
182 defer object.Close()
183
184 for _, key := range rv.MapKeys() {
185 keyName := fmt.Sprint(key.Interface())
186 if keyName == "" {
187 return &document.InvalidMarshalError{Message: "map key cannot be empty"}
188 }
189
190 ev := rv.MapIndex(key)
191 err := e.encode(jsonObjectKeyProvider{
192 Object: object,
193 Key: keyName,
194 }, ev, serde.Tag{})
195 if err != nil {
196 return err
197 }
198 }
199
200 return nil
201 }
202
203 func (e *Encoder) encodeSlice(value valueProvider, rv reflect.Value) error {
204 array := value.GetValue().Array()
205 defer array.Close()
206
207 for i := 0; i < rv.Len(); i++ {
208 err := e.encode(jsonArrayProvider{Array: array}, rv.Index(i), serde.Tag{})
209 if err != nil {
210 return err
211 }
212 }
213
214 return nil
215 }
216
217 func (e *Encoder) encodeScalar(vp valueProvider, rv reflect.Value) error {
218 if rv.Type() == serde.ReflectTypeOf.DocumentNumber {
219 number := rv.Interface().(document.Number)
220 if !isValidJSONNumber(number.String()) {
221 return &document.InvalidMarshalError{Message: fmt.Sprintf("invalid number literal: %s", number)}
222 }
223 vp.GetValue().Write([]byte(number))
224 }
225
226 switch rv.Kind() {
227 case reflect.Bool:
228 vp.GetValue().Boolean(rv.Bool())
229 case reflect.String:
230 vp.GetValue().String(rv.String())
231 default:
232
233 err := e.encodeNumber(vp, rv)
234 if err != nil {
235 return err
236 }
237 }
238
239 return nil
240 }
241
242 func (e *Encoder) encodeNumber(vp valueProvider, rv reflect.Value) error {
243 switch rv.Kind() {
244 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
245 vp.GetValue().Long(rv.Int())
246 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
247 vp.GetValue().ULong(rv.Uint())
248 case reflect.Float32:
249 vp.GetValue().Float(float32(rv.Float()))
250 case reflect.Float64:
251 vp.GetValue().Double(rv.Float())
252 default:
253 rvt := rv.Type()
254 switch {
255 case rvt.ConvertibleTo(serde.ReflectTypeOf.BigInt):
256 bi := rv.Convert(serde.ReflectTypeOf.BigInt).Interface().(big.Int)
257 vp.GetValue().BigInteger(&bi)
258 case rvt.ConvertibleTo(serde.ReflectTypeOf.BigFloat):
259 bf := rv.Convert(serde.ReflectTypeOf.BigFloat).Interface().(big.Float)
260 vp.GetValue().BigDecimal(&bf)
261 default:
262 return &document.InvalidMarshalError{Message: fmt.Sprintf("incompatible type: %s", rvt.String())}
263 }
264 }
265
266 return nil
267 }
268
269
270
271
272 func isValidJSONNumber(s string) bool {
273
274
275
276
277 if s == "" {
278 return false
279 }
280
281
282 if s[0] == '-' {
283 s = s[1:]
284 if s == "" {
285 return false
286 }
287 }
288
289
290 switch {
291 default:
292 return false
293
294 case s[0] == '0':
295 s = s[1:]
296
297 case '1' <= s[0] && s[0] <= '9':
298 s = s[1:]
299 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
300 s = s[1:]
301 }
302 }
303
304
305 if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
306 s = s[2:]
307 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
308 s = s[1:]
309 }
310 }
311
312
313
314 if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
315 s = s[1:]
316 if s[0] == '+' || s[0] == '-' {
317 s = s[1:]
318 if s == "" {
319 return false
320 }
321 }
322 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
323 s = s[1:]
324 }
325 }
326
327
328 return s == ""
329 }
View as plain text