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  }