Skip to content

Commit 596d703

Browse files
committed
incorporate review comments
Signed-off-by: Ashutosh Kumar <sonasingh46@gmail.com>
1 parent 2fafecc commit 596d703

File tree

2 files changed

+131
-31
lines changed

2 files changed

+131
-31
lines changed

types/nullable.go

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ import (
66
"fmt"
77
)
88

9-
// nullBytes is a JSON null literal
10-
var nullBytes = []byte("null")
11-
129
// Nullable type which can help distinguish between if a value was explicitly
1310
// provided `null` in JSON or not
1411
type Nullable[T any] struct {
@@ -20,7 +17,7 @@ type Nullable[T any] struct {
2017
// UnmarshalJSON implements the Unmarshaler interface.
2118
func (t *Nullable[T]) UnmarshalJSON(data []byte) error {
2219
t.Set = true
23-
if bytes.Equal(data, nullBytes) {
20+
if bytes.Equal(data, []byte("null")) {
2421
t.Null = true
2522
return nil
2623
}
@@ -33,20 +30,20 @@ func (t *Nullable[T]) UnmarshalJSON(data []byte) error {
3330

3431
// MarshalJSON implements the Marshaler interface.
3532
func (t Nullable[T]) MarshalJSON() ([]byte, error) {
36-
if t.IsNull() {
37-
return nullBytes, nil
33+
if t.Set && t.IsNull() {
34+
return []byte("null"), nil
3835
}
3936
return json.Marshal(t.Value)
4037
}
4138

4239
// IsNull returns true if the value is explicitly provided `null` in json
4340
func (t *Nullable[T]) IsNull() bool {
44-
return t.Null
41+
return t.Set && t.Null
4542
}
4643

47-
// IsSet returns true if the value is provided in json
48-
func (t *Nullable[T]) IsSet() bool {
49-
return t.Set
44+
// HasValue returns true if the value is explicitly provided in json
45+
func (t *Nullable[T]) HasValue() bool {
46+
return t.Set && t.Null
5047
}
5148

5249
func (t *Nullable[T]) Get() (value T, null bool) {

types/nullable_test.go

Lines changed: 124 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ package types
22

33
import (
44
"encoding/json"
5-
"fmt"
65
"github.com/stretchr/testify/assert"
6+
"github.com/stretchr/testify/require"
77
"testing"
88
)
99

@@ -48,13 +48,12 @@ func TestSimpleString(t *testing.T) {
4848
},
4949
}
5050
for _, tt := range tests {
51-
t.Run(tt.name, func(t1 *testing.T) {
51+
t.Run(tt.name, func(t *testing.T) {
5252
var obj SimpleString
5353
err := json.Unmarshal(tt.jsonInput, &obj)
54-
assert.NoError(t, err)
54+
require.NoError(t, err)
5555
assert.Equalf(t, tt.wantNull, obj.Name.IsNull(), "IsNull()")
56-
assert.Equalf(t, tt.wantSet, obj.Name.IsSet(), "IsSet()")
57-
fmt.Println(obj.Name.Get())
56+
assert.Equalf(t, tt.wantSet, obj.Name.Set, "Set")
5857
})
5958
}
6059
}
@@ -100,12 +99,12 @@ func TestSimpleInt(t *testing.T) {
10099
},
101100
}
102101
for _, tt := range tests {
103-
t.Run(tt.name, func(t1 *testing.T) {
102+
t.Run(tt.name, func(t *testing.T) {
104103
var obj SimpleInt
105104
err := json.Unmarshal(tt.jsonInput, &obj)
106-
assert.NoError(t, err)
105+
require.NoError(t, err)
107106
assert.Equalf(t, tt.wantNull, obj.ReplicaCount.IsNull(), "IsNull()")
108-
assert.Equalf(t, tt.wantSet, obj.ReplicaCount.IsSet(), "IsSet()")
107+
assert.Equalf(t, tt.wantSet, obj.ReplicaCount.Set, "Set")
109108
})
110109
}
111110
}
@@ -152,12 +151,12 @@ func TestSimplePointerInt(t *testing.T) {
152151
},
153152
}
154153
for _, tt := range tests {
155-
t.Run(tt.name, func(t1 *testing.T) {
154+
t.Run(tt.name, func(t *testing.T) {
156155
var obj SimplePointerInt
157156
err := json.Unmarshal(tt.jsonInput, &obj)
158-
assert.NoError(t, err)
157+
require.NoError(t, err)
159158
assert.Equalf(t, tt.wantNull, obj.ReplicaCount.IsNull(), "IsNull()")
160-
assert.Equalf(t, tt.wantSet, obj.ReplicaCount.IsSet(), "IsSet()")
159+
assert.Equalf(t, tt.wantSet, obj.ReplicaCount.Set, "Set")
161160
})
162161
}
163162
}
@@ -166,6 +165,18 @@ type TestComplex struct {
166165
SimpleInt Nullable[SimpleInt] `json:"simple_int"`
167166
SimpleString Nullable[SimpleString] `json:"simple_string"`
168167
StringList Nullable[[]string] `json:"string_list"`
168+
Metrics Nullable[Metrics] `json:"metrics"`
169+
Endpoint Nullable[*Endpoint] `json:"endpoint"`
170+
}
171+
172+
type Metrics struct {
173+
CPU Nullable[int] `json:"cpu"`
174+
RAM Nullable[int] `json:"ram"`
175+
}
176+
177+
type Endpoint struct {
178+
APIEndpoint Nullable[*string] `json:"api_endpoint"`
179+
AgentEndpoint Nullable[*string] `json:"agent_endpoint"`
169180
}
170181

171182
func TestMixed(t *testing.T) {
@@ -179,11 +190,11 @@ func TestMixed(t *testing.T) {
179190
name: "empty json input",
180191
jsonInput: []byte(`{}`),
181192
assert: func(obj TestComplex, t *testing.T) {
182-
assert.Equalf(t, false, obj.SimpleInt.Value.ReplicaCount.IsSet(), "replica count should not be set")
193+
assert.Equalf(t, false, obj.SimpleInt.Value.ReplicaCount.Set, "replica count should not be set")
183194
assert.Equalf(t, false, obj.SimpleInt.Value.ReplicaCount.IsNull(), "replica count should not be null")
184-
assert.Equalf(t, false, obj.SimpleString.Value.Name.IsSet(), "name should not be set")
195+
assert.Equalf(t, false, obj.SimpleString.Value.Name.Set, "name should not be set")
185196
assert.Equalf(t, false, obj.SimpleString.Value.Name.IsNull(), "name should not be null")
186-
assert.Equalf(t, false, obj.StringList.IsSet(), "string list should not be set")
197+
assert.Equalf(t, false, obj.StringList.Set, "string list should not be set")
187198
assert.Equalf(t, false, obj.StringList.IsNull(), "string list should not be null")
188199
},
189200
},
@@ -193,20 +204,22 @@ func TestMixed(t *testing.T) {
193204
jsonInput: []byte(`{"simple_int":{"replicaCount":1}}`),
194205
assert: func(obj TestComplex, t *testing.T) {
195206
assert.Equalf(t, false, obj.SimpleInt.Value.ReplicaCount.IsNull(), "replica count should NOT be null")
196-
assert.Equalf(t, true, obj.SimpleInt.Value.ReplicaCount.IsSet(), "replica count should be set")
197-
assert.Equalf(t, false, obj.SimpleString.Value.Name.IsSet(), "name should NOT be set")
207+
assert.Equalf(t, true, obj.SimpleInt.Value.ReplicaCount.Set, "replica count should be set")
208+
assert.Equalf(t, false, obj.SimpleString.Value.Name.Set, "name should NOT be set")
198209
assert.Equalf(t, false, obj.SimpleString.Value.Name.IsNull(), "name should NOT be null")
199210
gotValue, isNull := obj.SimpleInt.Value.ReplicaCount.Get()
200211
assert.Equalf(t, false, isNull, "replica count should NOT be null")
201212
assert.Equalf(t, 1, gotValue, "replica count should be 1")
213+
assert.Equalf(t, false, obj.Metrics.IsNull(), "metrics should not be null")
214+
assert.Equalf(t, false, obj.Metrics.Set, "metrics should not be set")
202215
},
203216
},
204217

205218
{
206219
name: "string list having null value",
207220
jsonInput: []byte(`{"string_list": null}`),
208221
assert: func(obj TestComplex, t *testing.T) {
209-
assert.Equalf(t, true, obj.StringList.IsSet(), "string_list should be set")
222+
assert.Equalf(t, true, obj.StringList.Set, "string_list should be set")
210223
assert.Equalf(t, true, obj.StringList.IsNull(), "string_list should be null")
211224
},
212225
},
@@ -215,7 +228,7 @@ func TestMixed(t *testing.T) {
215228
name: "string list having non null value",
216229
jsonInput: []byte(`{"string_list": ["foo", "bar"]}`),
217230
assert: func(obj TestComplex, t *testing.T) {
218-
assert.Equalf(t, true, obj.StringList.IsSet(), "string_list should be set")
231+
assert.Equalf(t, true, obj.StringList.Set, "string_list should be set")
219232
assert.Equalf(t, false, obj.StringList.IsNull(), "string_list should not be null")
220233
gotStringList, isNull := obj.StringList.Get()
221234
assert.Equalf(t, false, isNull, "string_list should not be null")
@@ -228,20 +241,110 @@ func TestMixed(t *testing.T) {
228241
name: "set string list having empty value",
229242
jsonInput: []byte(`{"string_list":[]}`),
230243
assert: func(obj TestComplex, t *testing.T) {
231-
assert.Equalf(t, true, obj.StringList.IsSet(), "string_list should be set")
244+
assert.Equalf(t, true, obj.StringList.Set, "string_list should be set")
232245
assert.Equalf(t, false, obj.StringList.IsNull(), "string_list should not be null")
246+
233247
gotStringList, isNull := obj.StringList.Get()
234248
assert.Equalf(t, false, isNull, "string_list should not be null")
235249
assert.Equalf(t, []string{}, gotStringList, "string_list should have the values as provided in the jSON")
236250

237251
},
238252
},
253+
254+
{
255+
name: "metrics having empty value",
256+
jsonInput: []byte(`{"metrics":{}}`),
257+
assert: func(obj TestComplex, t *testing.T) {
258+
assert.Equalf(t, true, obj.Metrics.Set, "metrics should not be set")
259+
assert.Equalf(t, false, obj.Metrics.IsNull(), "metrics should not be null")
260+
261+
assert.Equalf(t, false, obj.Metrics.Value.CPU.Set, "cpu metrics should not be set")
262+
assert.Equalf(t, false, obj.Metrics.Value.CPU.IsNull(), "ramt metrics should not be null")
263+
264+
assert.Equalf(t, false, obj.Metrics.Value.RAM.Set, "ram metrics should not be set")
265+
assert.Equalf(t, false, obj.Metrics.Value.RAM.IsNull(), "ram metrics should not be null")
266+
},
267+
},
268+
269+
{
270+
name: "metrics having null value",
271+
jsonInput: []byte(`{"metrics":null}`),
272+
assert: func(obj TestComplex, t *testing.T) {
273+
assert.Equalf(t, true, obj.Metrics.Set, "metrics should not be set")
274+
assert.Equalf(t, true, obj.Metrics.IsNull(), "metrics should not be null")
275+
276+
assert.Equalf(t, false, obj.Metrics.Value.CPU.Set, "cpu metrics should not be set")
277+
assert.Equalf(t, false, obj.Metrics.Value.CPU.IsNull(), "cpu metrics should not be null")
278+
279+
assert.Equalf(t, false, obj.Metrics.Value.RAM.Set, "ram metrics should not be set")
280+
assert.Equalf(t, false, obj.Metrics.Value.RAM.IsNull(), "ram metrics should not be null")
281+
},
282+
},
283+
284+
{
285+
name: "metrics having null value",
286+
jsonInput: []byte(`{}`),
287+
assert: func(obj TestComplex, t *testing.T) {
288+
assert.Equalf(t, false, obj.Metrics.Set, "metrics should not be set")
289+
assert.Equalf(t, false, obj.Metrics.IsNull(), "metrics should not be null")
290+
291+
assert.Equalf(t, false, obj.Metrics.Value.CPU.Set, "cpu metrics should not be set")
292+
assert.Equalf(t, false, obj.Metrics.Value.CPU.IsNull(), "ramt metrics should not be null")
293+
294+
assert.Equalf(t, false, obj.Metrics.Value.RAM.Set, "ram metrics should not be set")
295+
assert.Equalf(t, false, obj.Metrics.Value.RAM.IsNull(), "ram metrics should not be null")
296+
297+
},
298+
},
299+
300+
{
301+
name: "endpoint having empty value",
302+
jsonInput: []byte(`{"endpoint":{}}`),
303+
assert: func(obj TestComplex, t *testing.T) {
304+
assert.Equalf(t, true, obj.Endpoint.Set, "endpoint should be set")
305+
assert.Equalf(t, false, obj.Endpoint.IsNull(), "endpoint should not be null")
306+
307+
assert.Equalf(t, false, obj.Endpoint.Value.APIEndpoint.Set, "APIEndpoint should not be set")
308+
assert.Equalf(t, false, obj.Endpoint.Value.APIEndpoint.IsNull(), "APIEndpoint should not be null")
309+
310+
assert.Equalf(t, false, obj.Endpoint.Value.AgentEndpoint.Set, "AgentEndpoint should not be set")
311+
assert.Equalf(t, false, obj.Endpoint.Value.AgentEndpoint.IsNull(), "AgentEndpoint should not be null")
312+
313+
assert.Equalf(t, false, obj.Endpoint.Value == nil, "AgentEndpoint should not be null")
314+
assert.Equalf(t, true, obj.Endpoint.Value.APIEndpoint.Value == nil, "AgentEndpoint should not be null")
315+
assert.Equalf(t, true, obj.Endpoint.Value.APIEndpoint.Value == nil, "AgentEndpoint should not be null")
316+
317+
},
318+
},
319+
320+
{
321+
name: "endpoint having null value",
322+
jsonInput: []byte(`{"endpoint":null}`),
323+
assert: func(obj TestComplex, t *testing.T) {
324+
assert.Equalf(t, true, obj.Endpoint.Set, "Endpoint should be set")
325+
assert.Equalf(t, true, obj.Endpoint.IsNull(), "Endpoint should be null")
326+
327+
assert.Equalf(t, true, obj.Endpoint.Value == nil, "APIEndpoint should not be set")
328+
},
329+
},
330+
331+
{
332+
name: "endpoint not provided value",
333+
jsonInput: []byte(`{}`),
334+
assert: func(obj TestComplex, t *testing.T) {
335+
assert.Equalf(t, false, obj.Endpoint.Set, "Endpoint should not be set")
336+
assert.Equalf(t, false, obj.Endpoint.IsNull(), "Endpoint should not be null")
337+
338+
assert.Equalf(t, true, obj.Endpoint.Value == nil, "APIEndpoint should not be set")
339+
340+
},
341+
},
239342
}
240343
for _, tt := range tests {
241-
t.Run(tt.name, func(t1 *testing.T) {
344+
t.Run(tt.name, func(t *testing.T) {
242345
var obj TestComplex
243346
err := json.Unmarshal(tt.jsonInput, &obj)
244-
assert.NoError(t, err)
347+
require.NoError(t, err)
245348
tt.assert(obj, t)
246349
})
247350
}

0 commit comments

Comments
 (0)