package pgtype
import (
)
type JSONCodec struct {
Marshal func(v any) ([]byte, error)
Unmarshal func(data []byte, v any) error
}
func (*JSONCodec) ( int16) bool {
return == TextFormatCode || == BinaryFormatCode
}
func (*JSONCodec) () int16 {
return TextFormatCode
}
func ( *JSONCodec) ( *Map, uint32, int16, any) EncodePlan {
switch .(type) {
case string:
return encodePlanJSONCodecEitherFormatString{}
case []byte:
return encodePlanJSONCodecEitherFormatByteSlice{}
case json.RawMessage:
return encodePlanJSONCodecEitherFormatJSONRawMessage{}
case driver.Valuer:
return &encodePlanDriverValuer{m: , oid: , formatCode: }
case json.Marshaler:
return &encodePlanJSONCodecEitherFormatMarshal{
marshal: .Marshal,
}
}
for , := range []TryWrapEncodePlanFunc{
TryWrapDerefPointerEncodePlan,
TryWrapFindUnderlyingTypeEncodePlan,
} {
if , , := (); {
if := .(, , , ); != nil {
.SetNext()
return
}
}
}
return &encodePlanJSONCodecEitherFormatMarshal{
marshal: .Marshal,
}
}
type jsonPointerScanPlan struct {
next ScanPlan
}
func ( jsonPointerScanPlan) ( []byte, any) error {
:= reflect.ValueOf().Elem()
if == nil || string() == "null" {
.SetZero()
return nil
}
.Set(reflect.New(.Type().Elem()))
if .next != nil {
return .next.Scan(, .Interface())
}
return nil
}
type encodePlanJSONCodecEitherFormatString struct{}
func (encodePlanJSONCodecEitherFormatString) ( any, []byte) ( []byte, error) {
:= .(string)
= append(, ...)
return , nil
}
type encodePlanJSONCodecEitherFormatByteSlice struct{}
func (encodePlanJSONCodecEitherFormatByteSlice) ( any, []byte) ( []byte, error) {
:= .([]byte)
if == nil {
return nil, nil
}
= append(, ...)
return , nil
}
type encodePlanJSONCodecEitherFormatJSONRawMessage struct{}
func (encodePlanJSONCodecEitherFormatJSONRawMessage) ( any, []byte) ( []byte, error) {
:= .(json.RawMessage)
if == nil {
return nil, nil
}
= append(, ...)
return , nil
}
type encodePlanJSONCodecEitherFormatMarshal struct {
marshal func(v any) ([]byte, error)
}
func ( *encodePlanJSONCodecEitherFormatMarshal) ( any, []byte) ( []byte, error) {
, := .marshal()
if != nil {
return nil,
}
= append(, ...)
return , nil
}
func ( *JSONCodec) ( *Map, uint32, int16, any) ScanPlan {
return .planScan(, , , , 0)
}
func ( *JSONCodec) ( *Map, uint32, int16, any, int) ScanPlan {
if > 8 {
return &scanPlanFail{m: , oid: , formatCode: }
}
switch .(type) {
case *string:
return &scanPlanAnyToString{}
case *[]byte:
return &scanPlanJSONToByteSlice{}
case BytesScanner:
return &scanPlanBinaryBytesToBytesScanner{}
case sql.Scanner:
return &scanPlanCodecSQLScanner{c: , m: , oid: , formatCode: }
}
:= reflect.ValueOf()
if .Kind() == reflect.Pointer && .Elem().Kind() == reflect.Pointer {
var jsonPointerScanPlan
.next = .(, , , .Elem().Interface(), +1)
return
} else {
return &scanPlanJSONToJSONUnmarshal{unmarshal: .Unmarshal}
}
}
type scanPlanAnyToString struct{}
func (scanPlanAnyToString) ( []byte, any) error {
:= .(*string)
* = string()
return nil
}
type scanPlanJSONToByteSlice struct{}
func (scanPlanJSONToByteSlice) ( []byte, any) error {
:= .(*[]byte)
if == nil {
* = nil
return nil
}
* = make([]byte, len())
copy(*, )
return nil
}
type scanPlanJSONToJSONUnmarshal struct {
unmarshal func(data []byte, v any) error
}
func ( *scanPlanJSONToJSONUnmarshal) ( []byte, any) error {
if == nil {
:= reflect.ValueOf()
if .Kind() == reflect.Ptr {
:= .Elem()
switch .Kind() {
case reflect.Ptr, reflect.Slice, reflect.Map, reflect.Interface:
.Set(reflect.Zero(.Type()))
return nil
}
}
return fmt.Errorf("cannot scan NULL into %T", )
}
:= reflect.ValueOf()
if .Kind() != reflect.Pointer || .IsNil() {
return fmt.Errorf("cannot scan into non-pointer or nil destinations %T", )
}
:= .Elem()
.Set(reflect.Zero(.Type()))
return .unmarshal(, )
}
func ( *JSONCodec) ( *Map, uint32, int16, []byte) (driver.Value, error) {
if == nil {
return nil, nil
}
:= make([]byte, len())
copy(, )
return , nil
}
func ( *JSONCodec) ( *Map, uint32, int16, []byte) (any, error) {
if == nil {
return nil, nil
}
var any
:= .Unmarshal(, &)
return ,
}