Skip to content

Commit 22d3311

Browse files
authored
Merge pull request #1 from gKits/add-is-zero-method
Add IsZero method to all Null types to support omitzero
2 parents 71730e9 + 9174b55 commit 22d3311

11 files changed

Lines changed: 124 additions & 3 deletions

File tree

bool.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,7 @@ func (n *NullBool) Scan(src any) error {
3939
n.Valid = reflect.TypeOf(src) != nil
4040
return nil
4141
}
42+
43+
func (n *NullBool) IsZero() bool {
44+
return !n.Valid
45+
}

byte.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,7 @@ func (n *NullByte) Scan(src any) error {
3939
n.Valid = reflect.TypeOf(src) != nil
4040
return nil
4141
}
42+
43+
func (n *NullByte) IsZero() bool {
44+
return !n.Valid
45+
}

float64.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,7 @@ func (n *NullFloat64) Scan(src any) error {
3939
n.Valid = reflect.TypeOf(src) != nil
4040
return nil
4141
}
42+
43+
func (n *NullFloat64) IsZero() bool {
44+
return !n.Valid
45+
}

generic.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,7 @@ func (n *Null[T]) Scan(src any) error {
4040
n.Valid = reflect.TypeOf(src) != nil
4141
return nil
4242
}
43+
44+
func (n *Null[T]) IsZero() bool {
45+
return !n.Valid
46+
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/gkits/sqlnull
22

3-
go 1.23.2
3+
go 1.24
44

55
require (
66
github.com/mattn/go-sqlite3 v1.14.24

int16.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,7 @@ func (n *NullInt16) Scan(src any) error {
3939
n.Valid = reflect.TypeOf(src) != nil
4040
return nil
4141
}
42+
43+
func (n *NullInt16) IsZero() bool {
44+
return !n.Valid
45+
}

int32.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,7 @@ func (n *NullInt32) Scan(src any) error {
3939
n.Valid = reflect.TypeOf(src) != nil
4040
return nil
4141
}
42+
43+
func (n *NullInt32) IsZero() bool {
44+
return !n.Valid
45+
}

int64.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,7 @@ func (n *NullInt64) Scan(src any) error {
3939
n.Valid = reflect.TypeOf(src) != nil
4040
return nil
4141
}
42+
43+
func (n *NullInt64) IsZero() bool {
44+
return !n.Valid
45+
}

sqlnull_test.go

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ type target struct {
2424
Time sqlnull.NullTime `json:"time"`
2525
}
2626

27+
type targetOmitZero struct {
28+
Generic sqlnull.Null[string] `json:"generic,omitzero"`
29+
String sqlnull.NullString `json:"string,omitzero"`
30+
Bool sqlnull.NullBool `json:"bool,omitzero"`
31+
Byte sqlnull.NullByte `json:"byte,omitzero"`
32+
Int16 sqlnull.NullInt16 `json:"int16,omitzero"`
33+
Int32 sqlnull.NullInt32 `json:"int32,omitzero"`
34+
Int64 sqlnull.NullInt64 `json:"int64,omitzero"`
35+
Float64 sqlnull.NullFloat64 `json:"float64,omitzero"`
36+
Time sqlnull.NullTime `json:"time,omitzero"`
37+
}
38+
2739
func Test_MarshalJSON(t *testing.T) {
2840
cases := []struct {
2941
name string
@@ -98,7 +110,7 @@ func Test_UnmarshalJSON(t *testing.T) {
98110
want target
99111
}{
100112
{
101-
name: "successfully marshal with values",
113+
name: "successfully unmarshal with values",
102114
in: []byte(`{
103115
"generic": "generic",
104116
"string": "string",
@@ -123,7 +135,7 @@ func Test_UnmarshalJSON(t *testing.T) {
123135
},
124136
},
125137
{
126-
name: "successfully marshal with null",
138+
name: "successfully unmarshal with null",
127139
in: []byte(`{
128140
"generic": null,
129141
"string": null,
@@ -147,6 +159,21 @@ func Test_UnmarshalJSON(t *testing.T) {
147159
Time: sqlnull.NullTime{Time: time.Time{}, Valid: false},
148160
},
149161
},
162+
{
163+
name: "successfully unmarshal with empty json",
164+
in: []byte(`{}`),
165+
want: target{
166+
Generic: sqlnull.Null[string]{V: "", Valid: false},
167+
String: sqlnull.NullString{String: "", Valid: false},
168+
Bool: sqlnull.NullBool{Bool: false, Valid: false},
169+
Byte: sqlnull.NullByte{Byte: 0, Valid: false},
170+
Int16: sqlnull.NullInt16{Int16: 0, Valid: false},
171+
Int32: sqlnull.NullInt32{Int32: 0, Valid: false},
172+
Int64: sqlnull.NullInt64{Int64: 0, Valid: false},
173+
Float64: sqlnull.NullFloat64{Float64: 0, Valid: false},
174+
Time: sqlnull.NullTime{Time: time.Time{}, Valid: false},
175+
},
176+
},
150177
}
151178

152179
for _, c := range cases {
@@ -244,3 +271,61 @@ func Test_Scan(t *testing.T) {
244271
})
245272
}
246273
}
274+
275+
func Test_MarshalJSONOmitZero(t *testing.T) {
276+
cases := []struct {
277+
name string
278+
in targetOmitZero
279+
want string
280+
}{
281+
{
282+
name: "successfully marshal with values",
283+
in: targetOmitZero{
284+
Generic: sqlnull.Null[string]{V: "generic", Valid: true},
285+
String: sqlnull.NullString{String: "string", Valid: true},
286+
Bool: sqlnull.NullBool{Bool: true, Valid: true},
287+
Byte: sqlnull.NullByte{Byte: 255, Valid: true},
288+
Int16: sqlnull.NullInt16{Int16: 16, Valid: true},
289+
Int32: sqlnull.NullInt32{Int32: 32, Valid: true},
290+
Int64: sqlnull.NullInt64{Int64: 64, Valid: true},
291+
Float64: sqlnull.NullFloat64{Float64: 64.6464, Valid: true},
292+
Time: sqlnull.NullTime{Time: time.Date(2024, 10, 23, 17, 50, 0, 0, time.UTC), Valid: true},
293+
},
294+
want: `{
295+
"generic": "generic",
296+
"string": "string",
297+
"bool": true,
298+
"byte": 255,
299+
"int16": 16,
300+
"int32": 32,
301+
"int64": 64,
302+
"float64": 64.6464,
303+
"time": "2024-10-23T17:50:00Z"
304+
}`,
305+
},
306+
{
307+
name: "successfully marshal empty json",
308+
in: targetOmitZero{
309+
Generic: sqlnull.Null[string]{V: "generic", Valid: false},
310+
String: sqlnull.NullString{String: "string", Valid: false},
311+
Bool: sqlnull.NullBool{Bool: true, Valid: false},
312+
Byte: sqlnull.NullByte{Byte: 255, Valid: false},
313+
Int16: sqlnull.NullInt16{Int16: 16, Valid: false},
314+
Int32: sqlnull.NullInt32{Int32: 32, Valid: false},
315+
Int64: sqlnull.NullInt64{Int64: 64, Valid: false},
316+
Float64: sqlnull.NullFloat64{Float64: 64.6464, Valid: false},
317+
Time: sqlnull.NullTime{Time: time.Date(2024, 10, 23, 17, 50, 0, 0, time.UTC), Valid: false},
318+
},
319+
want: `{}`,
320+
},
321+
}
322+
323+
for _, c := range cases {
324+
t.Run(c.name, func(t *testing.T) {
325+
got, err := json.Marshal(c.in)
326+
t.Log(string(got))
327+
require.NoError(t, err)
328+
assert.JSONEq(t, c.want, string(got))
329+
})
330+
}
331+
}

string.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,7 @@ func (n *NullString) Scan(src any) error {
3939
n.Valid = reflect.TypeOf(src) != nil
4040
return nil
4141
}
42+
43+
func (n *NullString) IsZero() bool {
44+
return !n.Valid
45+
}

0 commit comments

Comments
 (0)