This repository has been archived by the owner on Apr 4, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
marshal.go
113 lines (101 loc) · 2.52 KB
/
marshal.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
package mejson
import (
"encoding/base64"
"fmt"
"gopkg.in/mgo.v2/bson"
"os"
"reflect"
"time"
)
type Mejson map[string]interface{}
func Marshal(in interface{}) (interface{}, error) {
// short circuit for nil
if in == nil {
return nil, nil
}
if reflect.TypeOf(in).Kind() == reflect.Slice {
if v, ok := in.([]byte); ok {
return marshalBinary(bson.Binary{0x00, v}), nil
}
v := reflect.ValueOf(in)
slice := make([]interface{}, v.Len())
for i := 0; i < v.Len(); i++ {
slice[i] = v.Index(i).Interface()
}
return marshalSlice(slice)
} else {
switch v := in.(type) {
case bson.M:
return marshalMap(v)
case map[string]interface{}:
return marshalMap(v)
case bson.D:
// todo write marshaller for doc to ensure serialization order
return marshalMap(v.Map())
case bson.Binary:
return marshalBinary(v), nil
case bson.ObjectId:
return marshalObjectId(v), nil
case time.Time:
return marshalTime(v), nil
case bson.MongoTimestamp:
return marshalTimestamp(v), nil
case bson.RegEx:
return marshalRegex(v), nil
case string, int, int64, bool, float64, uint8, uint32:
return v, nil
default:
fmt.Fprintf(os.Stderr, "mejson: unknown type: %T\n", v)
return v, nil
}
}
}
func marshalSlice(in []interface{}) (interface{}, error) {
result := make([]interface{}, len(in))
for idx, value := range in {
mejson, err := Marshal(value)
if err != nil {
return nil, err
}
result[idx] = mejson
}
return result, nil
}
func marshalMap(in bson.M) (map[string]interface{}, error) {
result := make(map[string]interface{})
for key, value := range in {
mejson, err := Marshal(value)
if err != nil {
return nil, err
}
result[key] = mejson
}
return result, nil
}
func marshalObjectId(in bson.ObjectId) map[string]interface{} {
return map[string]interface{}{"$oid": in.Hex()}
}
func marshalBinary(in bson.Binary) Mejson {
return map[string]interface{}{
"$type": fmt.Sprintf("%x", in.Kind),
"$binary": base64.StdEncoding.EncodeToString(in.Data),
}
}
func marshalTime(in time.Time) map[string]interface{} {
return map[string]interface{}{
"$date": int(in.UnixNano() / 1e6),
}
}
func marshalTimestamp(in bson.MongoTimestamp) map[string]interface{} {
//{ "$timestamp": { "t": <t>, "i": <i> } }
seconds, iteration := int32(in>>32), int32(in)
return map[string]interface{}{
"$timestamp": bson.M{"t": seconds, "i": iteration},
}
}
func marshalRegex(in bson.RegEx) map[string]interface{} {
return map[string]interface{}{
"$regex": in.Pattern,
"$options": in.Options,
}
}