Skip to content

Commit

Permalink
entity_unmarshal: handle null day hours (and other null values in obj…
Browse files Browse the repository at this point in the history
…ects)
  • Loading branch information
cdworak authored Mar 27, 2019
1 parent 5623455 commit 68b5b34
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 17 deletions.
2 changes: 2 additions & 0 deletions entity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ func TestEntityJSONSerialization(t *testing.T) {
{&CustomLocationEntity{LocationEntity: LocationEntity{Languages: &[]string{"English"}}}, `{"languages":["English"]}`},
{&CustomLocationEntity{LocationEntity: LocationEntity{Hours: nil}}, `{}`},
{&CustomLocationEntity{LocationEntity: LocationEntity{Hours: NullHours()}}, `{"hours":null}`},
{&CustomLocationEntity{LocationEntity: LocationEntity{Hours: NullableHours(&Hours{Monday: NullDayHours(), Tuesday: NullDayHours(), Wednesday: NullDayHours(), Thursday: NullDayHours(), Friday: NullDayHours(), Saturday: NullDayHours(), Sunday: NullDayHours()})}}, `{"hours":{"monday":null,"tuesday":null,"wednesday":null,"thursday":null,"friday":null,"saturday":null,"sunday":null}}`},
{&CustomLocationEntity{CustomEntity: CustomEntity{CFUrl: String("")}}, `{"cf_Url":""}`},
{&CustomLocationEntity{CustomEntity: CustomEntity{CFUrl: nil}}, `{}`},
{&CustomLocationEntity{CustomEntity: CustomEntity{CFTextList: &[]string{}}}, `{"cf_TextList":[]}`},
Expand Down Expand Up @@ -124,6 +125,7 @@ func TestEntityJSONDeserialization(t *testing.T) {
{`{"languages":[]}`, &CustomLocationEntity{LocationEntity: LocationEntity{Languages: &[]string{}}}},
{`{"languages":["English"]}`, &CustomLocationEntity{LocationEntity: LocationEntity{Languages: &[]string{"English"}}}},
{`{"hours":null}`, &CustomLocationEntity{LocationEntity: LocationEntity{Hours: NullHours()}}},
{`{"hours":{"monday":null,"tuesday":null,"wednesday":null,"thursday":null,"friday":null,"saturday":null,"sunday":null}}`, &CustomLocationEntity{LocationEntity: LocationEntity{Hours: NullableHours(&Hours{Monday: NullDayHours(), Tuesday: NullDayHours(), Wednesday: NullDayHours(), Thursday: NullDayHours(), Friday: NullDayHours(), Saturday: NullDayHours(), Sunday: NullDayHours()})}}},
{`{"cf_Url":""}`, &CustomLocationEntity{CustomEntity: CustomEntity{CFUrl: String("")}}},
{`{"cf_Url": "www.yext.com"}`, &CustomLocationEntity{CustomEntity: CustomEntity{CFUrl: String("www.yext.com")}}},
{`{"cf_TextList":[]}`, &CustomLocationEntity{CustomEntity: CustomEntity{CFTextList: &[]string{}}}},
Expand Down
44 changes: 27 additions & 17 deletions entity_unmarshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,45 @@ import (
"strings"
)

func UnmarshalEntityJSON(i interface{}, data []byte) error {
func unmarshal(i interface{}, m map[string]interface{}) interface{} {
var jsonTagToKey = map[string]string{}
val := reflect.ValueOf(i).Elem()
val := Indirect(reflect.ValueOf(i))
for i := 0; i < val.Type().NumField(); i++ {
field := val.Type().Field(i)
tag := strings.Replace(field.Tag.Get("json"), ",omitempty", "", -1)
jsonTagToKey[tag] = field.Name
}

var m map[string]interface{}
err := json.Unmarshal(data, &m)
if err != nil {
return err
}

for tag, val := range m {
if _, ok := jsonTagToKey[tag]; ok && val == nil {
v := reflect.ValueOf(i).Elem().FieldByName(jsonTagToKey[tag])
if _, ok := jsonTagToKey[tag]; ok {
if val == nil {
v := Indirect(reflect.ValueOf(i)).FieldByName(jsonTagToKey[tag])

// Check if double pointer
if v.Type().Kind() == reflect.Ptr {
t := v.Type()
for t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Ptr {
t = t.Elem()
// Check if double pointer
if v.Type().Kind() == reflect.Ptr {
t := v.Type()
for t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Ptr {
t = t.Elem()
}
typedNil := reflect.New(t)
Indirect(reflect.ValueOf(i)).FieldByName(jsonTagToKey[tag]).Set(reflect.ValueOf(typedNil.Interface()))
}
typedNil := reflect.New(t)
reflect.ValueOf(i).Elem().FieldByName(jsonTagToKey[tag]).Set(reflect.ValueOf(typedNil.Interface()))
} else if vMap, ok := val.(map[string]interface{}); ok {
v := Indirect(reflect.ValueOf(i)).FieldByName(jsonTagToKey[tag])
r := unmarshal(v.Interface(), vMap)
Indirect(reflect.ValueOf(i)).FieldByName(jsonTagToKey[tag]).Set(reflect.ValueOf(r))
}
}
}
return i
}

func UnmarshalEntityJSON(i interface{}, data []byte) error {
var m map[string]interface{}
err := json.Unmarshal(data, &m)
if err != nil {
return err
}
i = unmarshal(i, m)
return nil
}

0 comments on commit 68b5b34

Please sign in to comment.