@@ -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
41107type 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.
50114func (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.
65127func (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
73135func (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