Skip to content

Commit

Permalink
Add Interface Handler
Browse files Browse the repository at this point in the history
  • Loading branch information
abiewardani authored and agungdwiprasetyo committed Aug 6, 2019
1 parent 2e50135 commit 449703e
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 12 deletions.
10 changes: 5 additions & 5 deletions json_unmarshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@ func scanTarget(target reflect.Value, source interface{}) {
case reflect.Ptr:
scanTarget(target.Elem(), source)

case reflect.Interface:
target.Set(reflect.ValueOf(source))

}
}

Expand All @@ -63,7 +60,7 @@ func scanStructField(obj reflect.Value, data map[string]interface{}) {
for i := 0; i < obj.NumField(); i++ {
field := obj.Field(i)
if !field.CanSet() { // break if field cannot set a value (usually an unexported field in struct), to avoid a panic
return
continue
}

jsonTag := objType.Field(i).Tag.Get("json")
Expand All @@ -90,14 +87,17 @@ func setValue(targetField reflect.Value, data interface{}) (err error) {
valueSource := reflect.ValueOf(data) // valueSource is datatype from json source

// check target is pointer or not, and value from json data source
if targetKind == reflect.Ptr {
switch targetKind {
case reflect.Ptr:
if data != nil && targetField.IsNil() { // allocate new value to pointer target
rv := reflect.ValueOf(targetField.Interface())
val := reflect.New(rv.Type().Elem()).Interface()
targetField.Set(reflect.ValueOf(val))
}
targetField = targetField.Elem() // take the element if target is pointer, to set a value in target
targetKind = targetField.Kind()
case reflect.Interface:
targetField.Set(reflect.ValueOf(data))
}

// switch datatype from json source
Expand Down
17 changes: 10 additions & 7 deletions json_unmarshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ func TestUnmarshal(t *testing.T) {
Ss int `json:"ss"`
} `json:"testing"`
} `json:"obj"`
Slice []Slice `json:"slice"`
Strings []*string `json:"str"`
Ints []int `json:"ints"`
Bools []bool `json:"bools"`
NoTag string
skip string // cannot set value to this field because unexported
Slice []Slice `json:"slice"`
Strings []*string `json:"str"`
Ints []int `json:"ints"`
Bools []bool `json:"bools"`
NoTag string
skip string // cannot set value to this field because unexported
Interface interface{} `json:"interface"`
}

t.Run("Testcase #1: Testing Unmarshal with root is JSON Object", func(t *testing.T) {
Expand Down Expand Up @@ -66,7 +67,8 @@ func TestUnmarshal(t *testing.T) {
"str": ["a", true],
"ints": ["2", 3],
"bools": [1, "true", "0", true],
"NoTag": 19283091832
"NoTag": 19283091832,
"interface": 1
}`)
var target Model
err := Unmarshal(data, &target)
Expand All @@ -80,6 +82,7 @@ func TestUnmarshal(t *testing.T) {
assert.Equal(t, 2, target.Ints[0])
assert.Equal(t, false, target.Bools[2])
assert.Equal(t, "19283091832", target.NoTag)
assert.NotNil(t, target.Interface)

fmt.Printf("%+v\n\n", target)
})
Expand Down

0 comments on commit 449703e

Please sign in to comment.