package pgtype
import (
"database/sql"
"database/sql/driver"
"encoding/json"
"fmt"
"reflect"
)
type JSONCodec struct {}
func (JSONCodec ) FormatSupported (format int16 ) bool {
return format == TextFormatCode || format == BinaryFormatCode
}
func (JSONCodec ) PreferredFormat () int16 {
return TextFormatCode
}
func (c JSONCodec ) PlanEncode (m *Map , oid uint32 , format int16 , value any ) EncodePlan {
switch value .(type ) {
case string :
return encodePlanJSONCodecEitherFormatString {}
case []byte :
return encodePlanJSONCodecEitherFormatByteSlice {}
case json .Marshaler :
return encodePlanJSONCodecEitherFormatMarshal {}
case driver .Valuer :
return &encodePlanDriverValuer {m : m , oid : oid , formatCode : format }
}
for _ , f := range []TryWrapEncodePlanFunc {
TryWrapDerefPointerEncodePlan ,
TryWrapFindUnderlyingTypeEncodePlan ,
} {
if wrapperPlan , nextValue , ok := f (value ); ok {
if nextPlan := c .PlanEncode (m , oid , format , nextValue ); nextPlan != nil {
wrapperPlan .SetNext (nextPlan )
return wrapperPlan
}
}
}
return encodePlanJSONCodecEitherFormatMarshal {}
}
type encodePlanJSONCodecEitherFormatString struct {}
func (encodePlanJSONCodecEitherFormatString ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
jsonString := value .(string )
buf = append (buf , jsonString ...)
return buf , nil
}
type encodePlanJSONCodecEitherFormatByteSlice struct {}
func (encodePlanJSONCodecEitherFormatByteSlice ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
jsonBytes := value .([]byte )
if jsonBytes == nil {
return nil , nil
}
buf = append (buf , jsonBytes ...)
return buf , nil
}
type encodePlanJSONCodecEitherFormatMarshal struct {}
func (encodePlanJSONCodecEitherFormatMarshal ) Encode (value any , buf []byte ) (newBuf []byte , err error ) {
jsonBytes , err := json .Marshal (value )
if err != nil {
return nil , err
}
buf = append (buf , jsonBytes ...)
return buf , nil
}
func (JSONCodec ) PlanScan (m *Map , oid uint32 , format int16 , target any ) ScanPlan {
switch target .(type ) {
case *string :
return scanPlanAnyToString {}
case **string :
if wrapperPlan , nextDst , ok := TryPointerPointerScanPlan (target ); ok {
if nextPlan := m .planScan (oid , format , nextDst ); nextPlan != nil {
if _ , failed := nextPlan .(*scanPlanFail ); !failed {
wrapperPlan .SetNext (nextPlan )
return wrapperPlan
}
}
}
case *[]byte :
return scanPlanJSONToByteSlice {}
case BytesScanner :
return scanPlanBinaryBytesToBytesScanner {}
case sql .Scanner :
return &scanPlanSQLScanner {formatCode : format }
}
return scanPlanJSONToJSONUnmarshal {}
}
type scanPlanAnyToString struct {}
func (scanPlanAnyToString ) Scan (src []byte , dst any ) error {
p := dst .(*string )
*p = string (src )
return nil
}
type scanPlanJSONToByteSlice struct {}
func (scanPlanJSONToByteSlice ) Scan (src []byte , dst any ) error {
dstBuf := dst .(*[]byte )
if src == nil {
*dstBuf = nil
return nil
}
*dstBuf = make ([]byte , len (src ))
copy (*dstBuf , src )
return nil
}
type scanPlanJSONToBytesScanner struct {}
func (scanPlanJSONToBytesScanner ) Scan (src []byte , dst any ) error {
scanner := (dst ).(BytesScanner )
return scanner .ScanBytes (src )
}
type scanPlanJSONToJSONUnmarshal struct {}
func (scanPlanJSONToJSONUnmarshal ) Scan (src []byte , dst any ) error {
if src == nil {
dstValue := reflect .ValueOf (dst )
if dstValue .Kind () == reflect .Ptr {
el := dstValue .Elem ()
switch el .Kind () {
case reflect .Ptr , reflect .Slice , reflect .Map , reflect .Interface :
el .Set (reflect .Zero (el .Type ()))
return nil
}
}
return fmt .Errorf ("cannot scan NULL into %T" , dst )
}
elem := reflect .ValueOf (dst ).Elem ()
elem .Set (reflect .Zero (elem .Type ()))
return json .Unmarshal (src , dst )
}
func (c JSONCodec ) DecodeDatabaseSQLValue (m *Map , oid uint32 , format int16 , src []byte ) (driver .Value , error ) {
if src == nil {
return nil , nil
}
dstBuf := make ([]byte , len (src ))
copy (dstBuf , src )
return dstBuf , nil
}
func (c JSONCodec ) DecodeValue (m *Map , oid uint32 , format int16 , src []byte ) (any , error ) {
if src == nil {
return nil , nil
}
var dst any
err := json .Unmarshal (src , &dst )
return dst , err
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .