github.com/RevenueMonster/sqlike@v1.0.6/jsonb/encoder.go (about) 1 package jsonb 2 3 import ( 4 "bytes" 5 "encoding" 6 "encoding/base64" 7 "encoding/json" 8 "fmt" 9 "reflect" 10 "sort" 11 "strconv" 12 "time" 13 14 "github.com/RevenueMonster/sqlike/reflext" 15 ) 16 17 // DefaultEncoder : 18 type DefaultEncoder struct { 19 registry *Registry 20 } 21 22 // EncodeByte : 23 func (enc DefaultEncoder) EncodeByte(w *Writer, v reflect.Value) error { 24 if v.IsNil() { 25 w.WriteString(null) 26 return nil 27 } 28 w.WriteRune('"') 29 w.WriteString(base64.StdEncoding.EncodeToString(v.Bytes())) 30 w.WriteRune('"') 31 return nil 32 } 33 34 // EncodeStringer : 35 func (enc DefaultEncoder) EncodeStringer(w *Writer, v reflect.Value) error { 36 x := v.Interface().(fmt.Stringer) 37 w.WriteString(strconv.Quote(x.String())) 38 return nil 39 } 40 41 // EncodeJSONRaw : 42 func (enc DefaultEncoder) EncodeJSONRaw(w *Writer, v reflect.Value) error { 43 if v.IsNil() { 44 w.WriteString(null) 45 return nil 46 } 47 buf := new(bytes.Buffer) 48 if err := json.Compact(buf, v.Bytes()); err != nil { 49 return err 50 } 51 if buf.Len() == 0 { 52 w.Write([]byte(`{}`)) 53 return nil 54 } 55 w.Write(buf.Bytes()) 56 return nil 57 } 58 59 // EncodeTime : 60 func (enc DefaultEncoder) EncodeTime(w *Writer, v reflect.Value) error { 61 var temp [20]byte 62 x := v.Interface().(time.Time) 63 w.Write(x.UTC().AppendFormat(temp[:0], `"`+time.RFC3339Nano+`"`)) 64 return nil 65 } 66 67 // EncodeString : 68 func (enc DefaultEncoder) EncodeString(w *Writer, v reflect.Value) error { 69 w.WriteRune('"') 70 escapeString(w, v.String()) 71 w.WriteRune('"') 72 return nil 73 } 74 75 // EncodeBool : 76 func (enc DefaultEncoder) EncodeBool(w *Writer, v reflect.Value) error { 77 var temp [4]byte 78 w.Write(strconv.AppendBool(temp[:0], v.Bool())) 79 return nil 80 } 81 82 // EncodeInt : 83 func (enc DefaultEncoder) EncodeInt(w *Writer, v reflect.Value) error { 84 var temp [8]byte 85 w.Write(strconv.AppendInt(temp[:0], v.Int(), 10)) 86 return nil 87 } 88 89 // EncodeUint : 90 func (enc DefaultEncoder) EncodeUint(w *Writer, v reflect.Value) error { 91 var temp [10]byte 92 w.Write(strconv.AppendUint(temp[:0], v.Uint(), 10)) 93 return nil 94 } 95 96 // EncodeFloat : 97 func (enc DefaultEncoder) EncodeFloat(w *Writer, v reflect.Value) error { 98 f64 := v.Float() 99 if f64 <= 0 { 100 w.WriteRune('0') 101 return nil 102 } 103 w.WriteString(strconv.FormatFloat(f64, 'E', -1, 64)) 104 return nil 105 } 106 107 // EncodePtr : 108 func (enc *DefaultEncoder) EncodePtr(w *Writer, v reflect.Value) error { 109 if v.IsNil() { 110 w.WriteString(null) 111 return nil 112 } 113 114 v = v.Elem() 115 encoder, err := enc.registry.LookupEncoder(v) 116 if err != nil { 117 return err 118 } 119 return encoder(w, v) 120 } 121 122 // EncodeStruct : 123 func (enc *DefaultEncoder) EncodeStruct(w *Writer, v reflect.Value) error { 124 w.WriteRune('{') 125 mapper := reflext.DefaultMapper 126 cdc := mapper.CodecByType(v.Type()) 127 for i, sf := range cdc.Properties() { 128 if i > 0 { 129 w.WriteRune(',') 130 } 131 w.WriteString(strconv.Quote(sf.Name())) 132 w.WriteRune(':') 133 fv := mapper.FieldByIndexesReadOnly(v, sf.Index()) 134 encoder, err := enc.registry.LookupEncoder(fv) 135 if err != nil { 136 return err 137 } 138 if err := encoder(w, fv); err != nil { 139 return err 140 } 141 } 142 w.WriteRune('}') 143 return nil 144 } 145 146 // EncodeArray : 147 func (enc *DefaultEncoder) EncodeArray(w *Writer, v reflect.Value) error { 148 if v.Kind() == reflect.Slice && v.IsNil() { 149 w.WriteString(null) 150 return nil 151 } 152 w.WriteRune('[') 153 length := v.Len() 154 for i := 0; i < length; i++ { 155 if i > 0 { 156 w.WriteRune(',') 157 } 158 159 fv := v.Index(i) 160 encoder, err := enc.registry.LookupEncoder(fv) 161 if err != nil { 162 return err 163 } 164 if err := encoder(w, fv); err != nil { 165 return err 166 } 167 } 168 w.WriteRune(']') 169 return nil 170 } 171 172 // EncodeInterface : 173 func (enc *DefaultEncoder) EncodeInterface(w *Writer, v reflect.Value) error { 174 it := v.Interface() 175 if it == nil { 176 w.WriteString(null) 177 return nil 178 } 179 encoder, err := enc.registry.LookupEncoder(v) 180 if err != nil { 181 return err 182 } 183 return encoder(w, reflect.ValueOf(it)) 184 } 185 186 // EncodeMap : 187 func (enc *DefaultEncoder) EncodeMap(w *Writer, v reflect.Value) error { 188 t := v.Type() 189 k := t.Key() 190 if v.IsNil() { 191 w.WriteString(null) 192 return nil 193 } 194 195 w.WriteByte('{') 196 if v.Len() == 0 { 197 w.WriteByte('}') 198 return nil 199 } 200 201 keys := v.MapKeys() 202 var encode ValueEncoder 203 if k.Implements(textMarshaler) { 204 encode = func(wr *Writer, vi reflect.Value) error { 205 it := vi.Interface().(encoding.TextMarshaler) 206 b, err := it.MarshalText() 207 if err != nil { 208 return err 209 } 210 211 wr.WriteByte('"') 212 wr.Write(b) 213 wr.WriteByte('"') 214 return nil 215 } 216 } else { 217 switch k.Kind() { 218 case reflect.String: 219 sort.SliceStable(keys, func(i, j int) bool { 220 return keys[i].String() < keys[j].String() 221 }) 222 encode = enc.registry.kindEncoders[reflect.String] 223 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 224 sort.SliceStable(keys, func(i, j int) bool { 225 return keys[i].Int() < keys[j].Int() 226 }) 227 encode = func(wr *Writer, vi reflect.Value) error { 228 wr.WriteByte('"') 229 wr.WriteString(strconv.FormatInt(vi.Int(), 10)) 230 wr.WriteByte('"') 231 return nil 232 } 233 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 234 sort.SliceStable(keys, func(i, j int) bool { 235 return keys[i].Uint() < keys[j].Uint() 236 }) 237 encode = func(wr *Writer, vi reflect.Value) error { 238 wr.WriteByte('"') 239 wr.WriteString(strconv.FormatUint(vi.Uint(), 10)) 240 wr.WriteByte('"') 241 return nil 242 } 243 default: 244 return fmt.Errorf("jsonb: unsupported data type %q for map key, it must be string", k.Kind()) 245 } 246 247 } 248 249 // Question: do we really need to sort the key before encode? 250 251 length := len(keys) 252 for i := 0; i < length; i++ { 253 if i > 0 { 254 w.WriteByte(',') 255 } 256 k := keys[i] 257 val := v.MapIndex(k) 258 if err := encode(w, k); err != nil { 259 return err 260 } 261 w.WriteByte(':') 262 encoder, err := enc.registry.LookupEncoder(val) 263 if err != nil { 264 return err 265 } 266 if err := encoder(w, val); err != nil { 267 return err 268 } 269 } 270 w.WriteByte('}') 271 return nil 272 }