diff --git a/option.go b/option.go index ef102d3..02adda1 100644 --- a/option.go +++ b/option.go @@ -3,6 +3,7 @@ package gust import ( "encoding/json" "fmt" + "unsafe" ) // BoolOpt wraps a value as an Option. @@ -404,14 +405,20 @@ func (o *Option[T]) Replace(some T) (old Option[T]) { return old } +const null = "null" + func (o Option[T]) MarshalJSON() ([]byte, error) { if o.IsNone() { - return []byte("null"), nil + return []byte(null), nil } return json.Marshal(o.value) } func (o *Option[T]) UnmarshalJSON(b []byte) error { + o.value = nil + if *(*string)(unsafe.Pointer(&b)) == null { + return nil + } var value = new(T) err := json.Unmarshal(b, value) if err == nil { diff --git a/option_test.go b/option_test.go index 358304b..824ee58 100644 --- a/option_test.go +++ b/option_test.go @@ -32,3 +32,35 @@ func TestOptionJSON(t *testing.T) { assert.True(t, r4.IsNone()) assert.Equal(t, "json: cannot unmarshal number into Go value of type gust_test.T", err4.Error()) } + +func TestOptionJSON2(t *testing.T) { + type T struct { + Name gust.Option[string] + } + var r = T{Name: gust.Some("andeya")} + var b, err = json.Marshal(r) + assert.NoError(t, err) + assert.Equal(t, `{"Name":"andeya"}`, string(b)) + var r2 T + err2 := json.Unmarshal(b, &r2) + assert.NoError(t, err2) + assert.Equal(t, r, r2) + + var r3 = T{Name: gust.Some("")} + var b3, err3 = json.Marshal(r3) + assert.NoError(t, err3) + assert.Equal(t, `{"Name":""}`, string(b3)) + var r4 T + err4 := json.Unmarshal(b3, &r4) + assert.NoError(t, err4) + assert.Equal(t, r3, r4) + + var r5 = T{Name: gust.None[string]()} + var b5, err5 = json.Marshal(r5) + assert.NoError(t, err5) + assert.Equal(t, `{"Name":null}`, string(b5)) + var r6 T + err6 := json.Unmarshal(b5, &r6) + assert.NoError(t, err6) + assert.Equal(t, r5, r6) +}