This is an automated email from the ASF dual-hosted git repository. wongoo pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/dubbo-go-hessian2.git
The following commit(s) were added to refs/heads/master by this push: new 5c30aa7 fix issue 149 - embed struct (#150) 5c30aa7 is described below commit 5c30aa72877a41035784a9ea7c3b5b9077e4feb0 Author: huiren <zhr...@gmail.com> AuthorDate: Thu Feb 27 13:39:28 2020 +0800 fix issue 149 - embed struct (#150) * fix issue 149 - embed struct * remove serialUID * mapping extends to all feilds --- object.go | 31 +++++++----- object_test.go | 56 ++++++++++++++++++++++ .../src/main/java/test/TestCustomReply.java | 31 ++++++++++++ 3 files changed, 107 insertions(+), 11 deletions(-) diff --git a/object.go b/object.go index 4756148..ba06800 100644 --- a/object.go +++ b/object.go @@ -275,27 +275,36 @@ func (d *Decoder) decClassDef() (interface{}, error) { return classInfo{javaName: clsName, fieldNameList: fieldList}, nil } -func findField(name string, typ reflect.Type) (int, error) { +func findField(name string, typ reflect.Type) ([]int, error) { for i := 0; i < typ.NumField(); i++ { // matching tag first, then lowerCamelCase, SameCase, lowerCase - if val, has := typ.Field(i).Tag.Lookup(tagIdentifier); has && strings.Compare(val, name) == 0 { - return i, nil + typField := typ.Field(i) + + if val, has := typField.Tag.Lookup(tagIdentifier); has && strings.Compare(val, name) == 0 { + return []int{i}, nil } - fieldName := typ.Field(i).Name + fieldName := typField.Name switch { case strings.Compare(lowerCamelCase(fieldName), name) == 0: - return i, nil + return []int{i}, nil case strings.Compare(fieldName, name) == 0: - return i, nil + return []int{i}, nil case strings.Compare(strings.ToLower(fieldName), name) == 0: - return i, nil + return []int{i}, nil } + if typField.Anonymous && typField.Type.Kind() == reflect.Struct { + next, _ := findField(name, typField.Type) + if len(next) > 0 { + pos := []int{i} + return append(pos, next...), nil + } + } } - return 0, perrors.Errorf("failed to find field %s", name) + return []int{}, perrors.Errorf("failed to find field %s", name) } func (d *Decoder) decInstance(typ reflect.Type, cls classInfo) (interface{}, error) { @@ -317,11 +326,11 @@ func (d *Decoder) decInstance(typ reflect.Type, cls classInfo) (interface{}, err } // skip unexported anonymous field - if vv.Type().Field(index).PkgPath != "" { + if vv.Type().FieldByIndex(index).PkgPath != "" { continue } - field := vv.Field(index) + field := vv.FieldByIndex(index) if !field.CanSet() { return nil, perrors.Errorf("decInstance CanSet false for field %s", fieldName) } @@ -457,7 +466,7 @@ func (d *Decoder) decInstance(typ reflect.Type, cls classInfo) (interface{}, err } default: - return nil, perrors.Errorf("unknown struct member type: %v %v", kind, typ.Name()+"."+typ.Field(index).Name) + return nil, perrors.Errorf("unknown struct member type: %v %v", kind, typ.Name()+"."+typ.FieldByIndex(index).Name) } } // end for diff --git a/object_test.go b/object_test.go index 2bae724..187661b 100644 --- a/object_test.go +++ b/object_test.go @@ -558,3 +558,59 @@ func TestSkip(t *testing.T) { testDecodeFrameworkWithSkip(t, "customReplyTypedFixedList_Object", make([]Object, 1)) } + +type Animal struct { + Name string +} + +func (a Animal) JavaClassName() string { + return "test.Animal" +} + +type Dog struct { + Animal + Gender string +} + +func (dog Dog) JavaClassName() string { + return "test.Dog" +} + +type DogAll struct { + All bool + Name string + Gender string +} + +func (dog *DogAll) JavaClassName() string { + return "test.DogAll" +} + +// see https://github.com/apache/dubbo-go-hessian2/issues/149 +func TestIssue149_EmbedStructGoDecode(t *testing.T) { + t.Run(`extends to embed`, func(t *testing.T) { + RegisterPOJO(&Dog{}) + got, err := decodeJavaResponse(`customReplyExtendClass`, ``, false) + if err != nil { + t.Error(err) + } + + want := &Dog{Animal{`a dog`}, `male`} + if !reflect.DeepEqual(got, want) { + t.Errorf("want %v got %v", want, got) + } + }) + + t.Run(`extends to all fields`, func(t *testing.T) { + RegisterPOJO(&DogAll{}) + got, err := decodeJavaResponse(`customReplyExtendClassToSingleStruct`, ``, false) + if err != nil { + t.Error(err) + } + + want := &DogAll{true, `a dog`, `male`} + if !reflect.DeepEqual(got, want) { + t.Errorf("want %v got %v", want, got) + } + }) +} diff --git a/test_hessian/src/main/java/test/TestCustomReply.java b/test_hessian/src/main/java/test/TestCustomReply.java index a260f02..a907150 100644 --- a/test_hessian/src/main/java/test/TestCustomReply.java +++ b/test_hessian/src/main/java/test/TestCustomReply.java @@ -422,6 +422,37 @@ public class TestCustomReply { output.flush(); } + public void customReplyExtendClass() throws Exception { + Dog dog = new Dog(); + dog.name = "a dog"; + dog.gender = "male"; + output.writeObject(dog); + output.flush(); + } + + public void customReplyExtendClassToSingleStruct() throws Exception { + Dog dog = new DogAll(); + dog.name = "a dog"; + dog.gender = "male"; + output.writeObject(dog); + output.flush(); + } +} + +interface Leg { + public int legConnt = 4; +} + +class Animal { + public String name; +} + +class Dog extends Animal implements Serializable, Leg { + public String gender; +} + +class DogAll extends Dog { + public boolean all = true; } class TypedListTest implements Serializable {