Skip to content

Commit bfc1c43

Browse files
committed
refactor the code
Signed-off-by: Ashutosh Kumar <[email protected]>
1 parent b0733dd commit bfc1c43

File tree

3 files changed

+302
-544
lines changed

3 files changed

+302
-544
lines changed

types/nullable.go

Lines changed: 74 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,47 @@ import (
66
"fmt"
77
)
88

9-
type OptionalNullable[T any] struct {
9+
/*
10+
11+
Usage of NullableOptional Type:
12+
13+
Consider a go type as below:
14+
type Obj struct{
15+
field NullableOptional[<any_go_type>]
16+
}
17+
18+
1. Check if value is explicitly provided null
19+
if obj.field.IsNull() { // explicit null provided }
20+
21+
2. Check if a value is explicitly provided which is not null
22+
if obj.field.HasValue() { // some value provided which could be zero value but not null }
23+
24+
Caution:
25+
26+
A zero value should not be read before checking if it hasValue via `HasValue()`.
27+
For example an empty json object `{}` Marshals to zero value even if it is not
28+
explicitly provided in JSON.
29+
30+
Limitations:
31+
32+
The conversion of JSON date to NullableOptional type and then converting the
33+
concrete golang NullableOptional type back to JSON does not result in the original
34+
JSON for some of the cases meaning the operation is not idempotent.
35+
36+
Refer the test case TestNullableRequiredIdempotency
37+
*/
38+
39+
type NullableOptional[T any] struct {
1040
Value T
11-
// Set indicates whether the underlying Value was sent in the request TODO
41+
// Set indicates whether the underlying Value was sent in the request.
1242
Set bool
13-
// Null indicates whether the underlying Value was sent in the request as a literal `null` value. Should only be checked if Set==true TODO
43+
// Null indicates whether the underlying Value was sent in the request as a literal `null` value.
44+
// Should only be checked if Set==true.
1445
Null bool
1546
}
1647

1748
// UnmarshalJSON implements the Unmarshaler interface.
18-
func (t *OptionalNullable[T]) UnmarshalJSON(data []byte) error {
49+
func (t *NullableOptional[T]) UnmarshalJSON(data []byte) error {
1950
t.Set = true
2051
if bytes.Equal(data, []byte("null")) {
2152
t.Null = true
@@ -29,27 +60,58 @@ func (t *OptionalNullable[T]) UnmarshalJSON(data []byte) error {
2960
}
3061

3162
// MarshalJSON implements the Marshaler interface.
32-
func (t OptionalNullable[T]) MarshalJSON() ([]byte, error) {
63+
func (t NullableOptional[T]) MarshalJSON() ([]byte, error) {
3364
if t.Set && t.Null {
3465
return []byte("null"), nil
3566
}
3667
return json.Marshal(t.Value)
3768
}
3869

70+
// IsNull returns true if the value is explicitly provided `null`
71+
func (t *NullableOptional[T]) IsNull() bool {
72+
return t.Set && t.Null
73+
}
74+
75+
// HasValue returns true if the value is explicitly provided and is not `null`
76+
func (t *NullableOptional[T]) HasValue() bool {
77+
return t.Set && !t.Null
78+
}
79+
80+
/*
81+
82+
Usage of Nullable Type:
83+
84+
Consider a go type as below:
85+
type Obj struct{
86+
field Nullable[<any_go_type>]
87+
}
88+
89+
1. Check if value is explicitly provided null
90+
if obj.field.IsNull() { // explicit null provided }
91+
92+
2. Since Nullable type should be used with required fields, it does not have
93+
the ability to answer if it was set, assuming it always provided.
94+
95+
Limitations:
96+
97+
The conversion of JSON date to NullableOptional type and then converting the
98+
concrete golang NullableOptional type back to JSON does not result in the original
99+
JSON for some of the cases meaning the operation is not idempotent.
100+
101+
Refer the test case TestNullableOptionalIdempotency
102+
103+
*/
104+
39105
// Nullable type which can help distinguish between if a value was explicitly
40106
// provided `null` in JSON or not
41107
type Nullable[T any] struct {
42108
Value T
43-
// Set indicates whether the underlying Value was sent in the request TODO
44-
Set bool
45-
// Null indicates whether the underlying Value was sent in the request as a literal `null` value. Should only be checked if Set==true TODO
109+
// Null indicates whether the underlying Value was sent in the request as a literal `null` value.
46110
Null bool
47111
}
48112

49113
// UnmarshalJSON implements the Unmarshaler interface.
50114
func (t *Nullable[T]) UnmarshalJSON(data []byte) error {
51-
// fmt.Println("UnmarshalJSON")
52-
t.Set = true
53115
if bytes.Equal(data, []byte("null")) {
54116
t.Null = true
55117
return nil
@@ -63,22 +125,13 @@ func (t *Nullable[T]) UnmarshalJSON(data []byte) error {
63125

64126
// MarshalJSON implements the Marshaler interface.
65127
func (t Nullable[T]) MarshalJSON() ([]byte, error) {
66-
if t.Set && t.IsNull() {
128+
if t.IsNull() {
67129
return []byte("null"), nil
68130
}
69131
return json.Marshal(t.Value)
70132
}
71133

72134
// IsNull returns true if the value is explicitly provided `null` in json
73135
func (t *Nullable[T]) IsNull() bool {
74-
return t.Set && t.Null
75-
}
76-
77-
// HasValue returns true if the value is explicitly provided in json
78-
func (t *Nullable[T]) HasValue() bool {
79-
return t.Set && t.Null
80-
}
81-
82-
func (t *Nullable[T]) Get() (value T, null bool) {
83-
return t.Value, t.IsNull()
136+
return t.Null
84137
}

0 commit comments

Comments
 (0)