Skip to content

Commit

Permalink
fix: gjson customized slice unmarshal failed
Browse files Browse the repository at this point in the history
  • Loading branch information
FGYFFFF committed Nov 4, 2022
1 parent 2865efb commit 3f4c2e8
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 2 deletions.
13 changes: 11 additions & 2 deletions binding/gjson/gjson.go
Expand Up @@ -38,7 +38,10 @@ import (
"github.com/bytedance/go-tagexpr/v2/binding/gjson/internal/rt"
)

var programCache = caching.CreateProgramCache()
var (
programCache = caching.CreateProgramCache()
unmarshalerInterface = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
)

func init() {
gjson.DisableModifiers = true
Expand Down Expand Up @@ -97,7 +100,13 @@ func assign(jsval gjson.Result, goval reflect.Value) (err error) {
goval.Set(reflect.ValueOf(data))
} else {
if !jsval.IsArray() {
return nil
// canAddr: true, implement unmarshaler : true -> continue
// canAddr: true, implement unmarshaler : false -> return
// canAddr: false, implement unmarshaler : true -> return
// canAddr: false, implement unmarshaler : false -> return
if !goval.CanAddr() || !goval.Addr().Type().Implements(unmarshalerInterface) {
return nil
}
}
jsvals := jsval.Array()
slice := reflect.MakeSlice(t, len(jsvals), len(jsvals))
Expand Down
40 changes: 40 additions & 0 deletions binding/gjson/gjson_test.go
Expand Up @@ -236,3 +236,43 @@ func getFiledInfoWithMap(t reflect.Type) map[string][]int {
}
return sf
}


// MarshalJSON to output non base64 encoded []byte
func (j ByteSlice) MarshalJSON() ([]byte, error) {
if len(j) == 0 {
return []byte("null"), nil
}

return json.RawMessage(j).MarshalJSON()
}

// UnmarshalJSON to deserialize []byte
func (j *ByteSlice) UnmarshalJSON(b []byte) error {
result := json.RawMessage{}
err := result.UnmarshalJSON(b)
*j = ByteSlice(result)
return err
}

type ByteSlice []byte

func TestCustomizedGjsonUnmarshal(t *testing.T) {
str := `{"h1":{"h2":1}}`
type F struct {
H ByteSlice `json:"h1"`
}

obj := F{}
err := Unmarshal([]byte(str), &obj)

assert.NoError(t, err)
assert.Equal(t, "{\"h2\":1}", string(obj.H))

obj2 := F{}
err = json.Unmarshal([]byte(str), &obj2)
assert.NoError(t, err)
assert.Equal(t, "{\"h2\":1}", string(obj2.H))

assert.Equal(t, obj.H, obj2.H)
}

0 comments on commit 3f4c2e8

Please sign in to comment.