From f8d088cfb613ce0d72c28179b08fdedbce07f2a7 Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Fri, 2 Sep 2022 18:37:02 -0500 Subject: [PATCH] Fix JSON scan not completely overwriting destination See https://github.com/jackc/pgtype/pull/185 for original report in pgx v4 / pgtype. --- pgtype/json.go | 3 +++ pgtype/json_test.go | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/pgtype/json.go b/pgtype/json.go index 0a089059..d0d98fc9 100644 --- a/pgtype/json.go +++ b/pgtype/json.go @@ -134,6 +134,9 @@ func (scanPlanJSONToJSONUnmarshal) Scan(src []byte, dst any) error { 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) } diff --git a/pgtype/json_test.go b/pgtype/json_test.go index d9d28404..db20e576 100644 --- a/pgtype/json_test.go +++ b/pgtype/json_test.go @@ -93,3 +93,16 @@ func TestJSONCodecUnmarshalSQLNull(t *testing.T) { require.EqualError(t, err, "can't scan into dest[0]: cannot scan NULL into *int") }) } + +func TestJSONCodecClearExistingValueBeforeUnmarshal(t *testing.T) { + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + m := map[string]any{} + err := conn.QueryRow(ctx, `select '{"foo": "bar"}'::json`).Scan(&m) + require.NoError(t, err) + require.Equal(t, map[string]any{"foo": "bar"}, m) + + err = conn.QueryRow(ctx, `select '{"baz": "quz"}'::json`).Scan(&m) + require.NoError(t, err) + require.Equal(t, map[string]any{"baz": "quz"}, m) + }) +}