Skip to content

Commit

Permalink
refactor the code
Browse files Browse the repository at this point in the history
Signed-off-by: Ashutosh Kumar <[email protected]>
  • Loading branch information
sonasingh46 committed Jan 8, 2024
1 parent b0733dd commit bfc1c43
Show file tree
Hide file tree
Showing 3 changed files with 302 additions and 544 deletions.
95 changes: 74 additions & 21 deletions types/nullable.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,47 @@ import (
"fmt"
)

type OptionalNullable[T any] struct {
/*
Usage of NullableOptional Type:
Consider a go type as below:
type Obj struct{
field NullableOptional[<any_go_type>]
}
1. Check if value is explicitly provided null
if obj.field.IsNull() { // explicit null provided }
2. Check if a value is explicitly provided which is not null
if obj.field.HasValue() { // some value provided which could be zero value but not null }
Caution:
A zero value should not be read before checking if it hasValue via `HasValue()`.
For example an empty json object `{}` Marshals to zero value even if it is not
explicitly provided in JSON.
Limitations:
The conversion of JSON date to NullableOptional type and then converting the
concrete golang NullableOptional type back to JSON does not result in the original
JSON for some of the cases meaning the operation is not idempotent.
Refer the test case TestNullableRequiredIdempotency
*/

type NullableOptional[T any] struct {
Value T
// Set indicates whether the underlying Value was sent in the request TODO
// Set indicates whether the underlying Value was sent in the request.
Set bool
// Null indicates whether the underlying Value was sent in the request as a literal `null` value. Should only be checked if Set==true TODO
// Null indicates whether the underlying Value was sent in the request as a literal `null` value.
// Should only be checked if Set==true.
Null bool
}

// UnmarshalJSON implements the Unmarshaler interface.
func (t *OptionalNullable[T]) UnmarshalJSON(data []byte) error {
func (t *NullableOptional[T]) UnmarshalJSON(data []byte) error {
t.Set = true
if bytes.Equal(data, []byte("null")) {
t.Null = true
Expand All @@ -29,27 +60,58 @@ func (t *OptionalNullable[T]) UnmarshalJSON(data []byte) error {
}

// MarshalJSON implements the Marshaler interface.
func (t OptionalNullable[T]) MarshalJSON() ([]byte, error) {
func (t NullableOptional[T]) MarshalJSON() ([]byte, error) {
if t.Set && t.Null {
return []byte("null"), nil
}
return json.Marshal(t.Value)
}

// IsNull returns true if the value is explicitly provided `null`
func (t *NullableOptional[T]) IsNull() bool {
return t.Set && t.Null
}

// HasValue returns true if the value is explicitly provided and is not `null`
func (t *NullableOptional[T]) HasValue() bool {
return t.Set && !t.Null
}

/*
Usage of Nullable Type:
Consider a go type as below:
type Obj struct{
field Nullable[<any_go_type>]
}
1. Check if value is explicitly provided null
if obj.field.IsNull() { // explicit null provided }
2. Since Nullable type should be used with required fields, it does not have
the ability to answer if it was set, assuming it always provided.
Limitations:
The conversion of JSON date to NullableOptional type and then converting the
concrete golang NullableOptional type back to JSON does not result in the original
JSON for some of the cases meaning the operation is not idempotent.
Refer the test case TestNullableOptionalIdempotency
*/

// Nullable type which can help distinguish between if a value was explicitly
// provided `null` in JSON or not
type Nullable[T any] struct {
Value T
// Set indicates whether the underlying Value was sent in the request TODO
Set bool
// Null indicates whether the underlying Value was sent in the request as a literal `null` value. Should only be checked if Set==true TODO
// Null indicates whether the underlying Value was sent in the request as a literal `null` value.
Null bool
}

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

// MarshalJSON implements the Marshaler interface.
func (t Nullable[T]) MarshalJSON() ([]byte, error) {
if t.Set && t.IsNull() {
if t.IsNull() {
return []byte("null"), nil
}
return json.Marshal(t.Value)
}

// IsNull returns true if the value is explicitly provided `null` in json
func (t *Nullable[T]) IsNull() bool {
return t.Set && t.Null
}

// HasValue returns true if the value is explicitly provided in json
func (t *Nullable[T]) HasValue() bool {
return t.Set && t.Null
}

func (t *Nullable[T]) Get() (value T, null bool) {
return t.Value, t.IsNull()
return t.Null
}
Loading

0 comments on commit bfc1c43

Please sign in to comment.