You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by wo...@apache.org on 2020/03/02 09:24:48 UTC

[dubbo-go-hessian2] branch master updated: Flat anonymous struct field (#154)

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 6ae5479  Flat anonymous  struct field (#154)
6ae5479 is described below

commit 6ae5479d93a3c5ef0f9b032554ed920b5a82308b
Author: huiren <zh...@gmail.com>
AuthorDate: Mon Mar 2 17:24:33 2020 +0800

    Flat anonymous  struct field (#154)
    
    * fix issue 149 - embed struct
    
    * remove serialUID
    
    * mapping extends to all feilds
    
    * flat
    
    * readme
    
    * update readme
---
 README.md                                          |  7 +++-
 object.go                                          | 37 ++++++++++++-----
 object_test.go                                     | 20 ++++++++-
 pojo.go                                            | 48 ++++++++++++++++------
 .../src/main/java/test/TestCustomDecode.java       |  5 +++
 5 files changed, 91 insertions(+), 26 deletions(-)

diff --git a/README.md b/README.md
index 5373648..90ddf82 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,7 @@ It's a golang hessian library used by [Apache/dubbo-go](https://github.com/apach
 * [Java Bigdecimal](https://github.com/apache/dubbo-go-hessian2/issues/89)
 * [Java Date & Time](https://github.com/apache/dubbo-go-hessian2/issues/90)
 * [Java Generic Invokation](https://github.com/apache/dubbo-go-hessian2/issues/84)
+* [Java Extends](https://github.com/apache/dubbo-go-hessian2/issues/157)
 * [Dubbo Attachements](https://github.com/apache/dubbo-go-hessian2/issues/49)
 * [Skipping unregistered POJO](https://github.com/apache/dubbo-go-hessian2/pull/128)
 * [Emoji](https://github.com/apache/dubbo-go-hessian2/issues/129)
@@ -60,11 +61,15 @@ So we can maintain a cross language type mapping:
 
 ```go
 type Circular struct {
-	Num      int
+	Value
 	Previous *Circular
 	Next     *Circular
 }
 
+type Value struct {
+	Num int
+}
+
 func (Circular) JavaClassName() string {
 	return "com.company.Circular"
 }
diff --git a/object.go b/object.go
index ba06800..857ae05 100644
--- a/object.go
+++ b/object.go
@@ -160,18 +160,35 @@ func (e *Encoder) encObject(v POJO) error {
 		e.buffer = encString(e.buffer, v.(POJOEnum).String())
 		return nil
 	}
-	num = vv.NumField()
-	for i = 0; i < num; i++ {
-		// skip unexported anonymous field
-		if vv.Type().Field(i).PkgPath != "" {
-			continue
-		}
 
-		field := vv.Field(i)
-		if err = e.Encode(field.Interface()); err != nil {
-			fieldName := field.Type().String()
-			return perrors.Wrapf(err, "failed to encode field: %s, %+v", fieldName, field.Interface())
+	structs := []reflect.Value{vv}
+	for len(structs) > 0 {
+		vv := structs[0]
+		num = vv.NumField()
+		for i = 0; i < num; i++ {
+			// skip unexported anonymous field
+			if vv.Type().Field(i).PkgPath != "" {
+				continue
+			}
+
+			// skip ignored field
+			if tag, _ := vv.Type().Field(i).Tag.Lookup(tagIdentifier); tag == `-` {
+				continue
+			}
+
+			field := vv.Field(i)
+			if vv.Type().Field(i).Anonymous && field.Kind() == reflect.Struct {
+				structs = append(structs, vv.Field(i))
+				continue
+			}
+
+			if err = e.Encode(field.Interface()); err != nil {
+				fieldName := field.Type().String()
+				return perrors.Wrapf(err, "failed to encode field: %s, %+v", fieldName, field.Interface())
+			}
 		}
+
+		structs = structs[1:]
 	}
 
 	return nil
diff --git a/object_test.go b/object_test.go
index 187661b..81238e1 100644
--- a/object_test.go
+++ b/object_test.go
@@ -563,13 +563,19 @@ type Animal struct {
 	Name string
 }
 
+type animal struct {
+	Name string
+}
+
 func (a Animal) JavaClassName() string {
 	return "test.Animal"
 }
 
 type Dog struct {
 	Animal
-	Gender string
+	animal
+	Gender  string
+	DogName string `hessian:"-"`
 }
 
 func (dog Dog) JavaClassName() string {
@@ -595,7 +601,7 @@ func TestIssue149_EmbedStructGoDecode(t *testing.T) {
 			t.Error(err)
 		}
 
-		want := &Dog{Animal{`a dog`}, `male`}
+		want := &Dog{Animal{`a dog`}, animal{}, `male`, ``}
 		if !reflect.DeepEqual(got, want) {
 			t.Errorf("want %v got %v", want, got)
 		}
@@ -614,3 +620,13 @@ func TestIssue149_EmbedStructGoDecode(t *testing.T) {
 		}
 	})
 }
+func TestIssue150_EmbedStructJavaDecode(t *testing.T) {
+	RegisterPOJO(&Dog{})
+	RegisterPOJO(&Animal{})
+
+	dog := &Dog{Animal{`a dog`}, animal{}, `male`, `DogName`}
+	bytes, err := encodeTarget(dog)
+	t.Log(string(bytes), err)
+
+	testJavaDecode(t, "customArgTypedFixed_Extends", dog)
+}
diff --git a/pojo.go b/pojo.go
index fb0879c..ed5ab8b 100644
--- a/pojo.go
+++ b/pojo.go
@@ -150,21 +150,43 @@ func RegisterPOJO(o POJO) int {
 	registerTypeName(structInfo.goName, structInfo.javaName)
 
 	// prepare fields info of objectDef
-	for i := 0; i < structInfo.typ.NumField(); i++ {
-		// skip unexported anonymous filed
-		if structInfo.typ.Field(i).PkgPath != "" {
-			continue
+	nextStruct := []reflect.Type{structInfo.typ}
+	for len(nextStruct) > 0 {
+		current := nextStruct[0]
+
+		for i := 0; i < current.NumField(); i++ {
+
+			// skip unexported anonymous filed
+			if current.Field(i).PkgPath != "" {
+				continue
+			}
+
+			structField := current.Field(i)
+
+			// skip ignored field
+			tagVal, hasTag := structField.Tag.Lookup(tagIdentifier)
+			if tagVal == `-` {
+				continue
+			}
+
+			// flat anonymous field
+			if structField.Anonymous && structField.Type.Kind() == reflect.Struct {
+				nextStruct = append(nextStruct, structField.Type)
+				continue
+			}
+
+			var fieldName string
+			if hasTag {
+				fieldName = tagVal
+			} else {
+				fieldName = lowerCamelCase(structField.Name)
+			}
+
+			fieldList = append(fieldList, fieldName)
+			bBody = encString(bBody, fieldName)
 		}
 
-		var fieldName string
-		if val, has := structInfo.typ.Field(i).Tag.Lookup(tagIdentifier); has {
-			fieldName = val
-		} else {
-			fieldName = lowerCamelCase(structInfo.typ.Field(i).Name)
-		}
-
-		fieldList = append(fieldList, fieldName)
-		bBody = encString(bBody, fieldName)
+		nextStruct = nextStruct[1:]
 	}
 
 	// prepare header of objectDef
diff --git a/test_hessian/src/main/java/test/TestCustomDecode.java b/test_hessian/src/main/java/test/TestCustomDecode.java
index 9e72a0a..f06fc99 100644
--- a/test_hessian/src/main/java/test/TestCustomDecode.java
+++ b/test_hessian/src/main/java/test/TestCustomDecode.java
@@ -187,6 +187,11 @@ public class TestCustomDecode {
         return o.toString().equals("100.256");
     }
 
+    public Object customArgTypedFixed_Extends() throws Exception {
+        Dog o = (Dog) input.readObject();
+        return o.name.equals("a dog") && o.gender.equals("male");
+    }
+
     public Object customArgTypedFixed_DateNull() throws Exception {
         DateDemo o = (DateDemo) input.readObject();
         return o.getDate() == null && o.getDate1() == null;