mirror of https://github.com/jackc/pgx.git
Fix issue with order of json encoding #1805
parent
94e56e61ba
commit
7ebced92b5
|
@ -25,18 +25,21 @@ func (c JSONCodec) PlanEncode(m *Map, oid uint32, format int16, value any) Encod
|
|||
case []byte:
|
||||
return encodePlanJSONCodecEitherFormatByteSlice{}
|
||||
|
||||
// Cannot rely on driver.Valuer being handled later because anything can be marshalled.
|
||||
//
|
||||
// https://github.com/jackc/pgx/issues/1430
|
||||
//
|
||||
// Check for driver.Valuer must come before json.Marshaler so that it is guaranteed to beused
|
||||
// when both are implemented https://github.com/jackc/pgx/issues/1805
|
||||
case driver.Valuer:
|
||||
return &encodePlanDriverValuer{m: m, oid: oid, formatCode: format}
|
||||
|
||||
// Must come before trying wrap encode plans because a pointer to a struct may be unwrapped to a struct that can be
|
||||
// marshalled.
|
||||
//
|
||||
// https://github.com/jackc/pgx/issues/1681
|
||||
case json.Marshaler:
|
||||
return encodePlanJSONCodecEitherFormatMarshal{}
|
||||
|
||||
// Cannot rely on driver.Valuer being handled later because anything can be marshalled.
|
||||
//
|
||||
// https://github.com/jackc/pgx/issues/1430
|
||||
case driver.Valuer:
|
||||
return &encodePlanDriverValuer{m: m, oid: oid, formatCode: format}
|
||||
}
|
||||
|
||||
// Because anything can be marshalled the normal wrapping in Map.PlanScan doesn't get a chance to run. So try the
|
||||
|
|
|
@ -3,6 +3,9 @@ package pgtype_test
|
|||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
pgx "github.com/jackc/pgx/v5"
|
||||
|
@ -55,6 +58,9 @@ func TestJSONCodec(t *testing.T) {
|
|||
|
||||
// Test driver.Valuer. (https://github.com/jackc/pgx/issues/1430)
|
||||
{sql.NullInt64{Int64: 42, Valid: true}, new(sql.NullInt64), isExpectedEq(sql.NullInt64{Int64: 42, Valid: true})},
|
||||
|
||||
// Test driver.Valuer is used before json.Marshaler (https://github.com/jackc/pgx/issues/1805)
|
||||
{Issue1805(7), new(Issue1805), isExpectedEq(Issue1805(7))},
|
||||
})
|
||||
|
||||
pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, pgxtest.KnownOIDQueryExecModes, "json", []pgxtest.ValueRoundTripTest{
|
||||
|
@ -68,6 +74,39 @@ func TestJSONCodec(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
type Issue1805 int
|
||||
|
||||
func (i *Issue1805) Scan(src any) error {
|
||||
var source []byte
|
||||
switch src.(type) {
|
||||
case string:
|
||||
source = []byte(src.(string))
|
||||
case []byte:
|
||||
source = src.([]byte)
|
||||
default:
|
||||
return errors.New("unknown source type")
|
||||
}
|
||||
var newI int
|
||||
if err := json.Unmarshal(source, &newI); err != nil {
|
||||
return err
|
||||
}
|
||||
*i = Issue1805(newI)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i Issue1805) Value() (driver.Value, error) {
|
||||
b, err := json.Marshal(int(i))
|
||||
return string(b), err
|
||||
}
|
||||
|
||||
func (i Issue1805) UnmarshalJSON(bytes []byte) error {
|
||||
return errors.New("UnmarshalJSON called")
|
||||
}
|
||||
|
||||
func (i Issue1805) MarshalJSON() ([]byte, error) {
|
||||
return nil, errors.New("MarshalJSON called")
|
||||
}
|
||||
|
||||
// https://github.com/jackc/pgx/issues/1273#issuecomment-1221414648
|
||||
func TestJSONCodecUnmarshalSQLNull(t *testing.T) {
|
||||
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
|
||||
|
|
Loading…
Reference in New Issue