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 {

Reply via email to