github.com/jxskiss/gopkg/v2@v2.14.9-0.20240514120614-899f3e7952b4/utils/sqlutil/types_json.go (about) 1 package sqlutil 2 3 import ( 4 "bytes" 5 "database/sql/driver" 6 "fmt" 7 8 "github.com/jxskiss/gopkg/v2/easy/ezmap" 9 "github.com/jxskiss/gopkg/v2/internal/unsafeheader" 10 "github.com/jxskiss/gopkg/v2/perf/json" 11 ) 12 13 //nolint:unused 14 var ( 15 null = []byte("null") 16 emptyObject = []byte("{}") 17 ) 18 19 // JSON holds a map[string]any value, it implements 20 // sql/driver.Valuer and sql.Scanner. It uses JSON to do serialization. 21 // 22 // JSON embeds a gemap.Map, thus all methods defined on gemap.Map is also 23 // available from a JSON instance. 24 type JSON struct { 25 ezmap.Map 26 } 27 28 // Value implements driver.Valuer interface. 29 func (p JSON) Value() (driver.Value, error) { 30 if p.Map == nil { 31 return emptyObject, nil 32 } 33 34 buf := bytes.NewBuffer(nil) 35 enc := json.NewEncoder(buf) 36 enc.SetEscapeHTML(false) 37 err := enc.Encode(p.Map) 38 if err != nil { 39 return nil, err 40 } 41 return buf.Bytes(), nil 42 } 43 44 // Scan implements sql.Scanner interface. 45 func (p *JSON) Scan(src any) error { 46 var data []byte 47 switch v := src.(type) { 48 case []byte: 49 data = v 50 case string: 51 data = unsafeheader.StringToBytes(v) 52 default: 53 return fmt.Errorf("sqlutil.JSON.Scan: want []byte/string but got %T", src) 54 } 55 56 dec := json.NewDecoder(bytes.NewReader(data)) 57 dec.UseNumber() 58 return dec.Decode(&p.Map) 59 } 60 61 func (p JSON) MarshalJSON() ([]byte, error) { 62 return json.Marshal(p.Map) 63 } 64 65 func (p *JSON) UnmarshalJSON(data []byte) error { 66 return json.Unmarshal(data, &p.Map) 67 }