Repository: apache/dubbo-go-hessian2 (go)

Issue:
结构体序列化再反序列化，不能完全还原
**What happened**:

```go
func init() {
	RegisterPOJO(new(Args1))
       RegisterPOJO(new(MockData))
}

type Args1 struct {
	Label string
	Key   string
}

func (Args1) JavaClassName() string {
	return "com.test.Args1"
}

type MockData struct {
	Args []interface{}
}

func (MockData) JavaClassName() string {
	return "com.Mock"
}

func TestHessianEncode(t *testing.T) {
	d := &MockData{
		Args: []interface{}{
			[]*Args1{
				{Label: "1", Key: "2"},
			},
		},
	}

	encoder := NewEncoder()
	err := encoder.Encode(d)
	if err != nil {
		t.Errorf("encode obj error: %v", err)
		return
	}
	decoder := NewDecoder(encoder.Buffer())
	doInterface, err := decoder.Decode()
	if err != nil {
		t.Errorf("decode obj error: %v", err)
		return
	}
	do := doInterface.(*MockData)
	if !reflect.DeepEqual(d, do) {
		t.Errorf("not equal d: %+v, do: %+v", d, do)
		return
	}
}
```

unit test log

```log
=== RUN   TestHessianEncode
    string_test.go:319: not equal d: &{Args:[[0xc000069100]]}, do: &{Args:[0xc0001097d0]}
--- FAIL: TestHessianEncode (0.00s)
```

**What you expected to happen**:

这个场景可以做到前后对象的一致吗？

**How to reproduce it (as minimally and precisely as possible)**:

**Anything else we need to know?**:


Pull request:
fix list value not unpacked
**What this PR does**:
fix list value not unpacked

**Which issue(s) this PR fixes**:
Fixes #299

**Special notes for your reviewer**:

**Does this PR introduce a user-facing change?**:
```release-note
- fix list value not unpacked. #299
```

Patch:
diff --git a/codec.go b/codec.go
index 1726438..161bf11 100644
--- a/codec.go
+++ b/codec.go
@@ -209,15 +209,7 @@ func EnsureInterface(in interface{}, err error) (interface{}, error) {
 		return in, err
 	}
 
-	if v, ok := in.(reflect.Value); ok {
-		in = v.Interface()
-	}
-
-	if v, ok := in.(*_refHolder); ok {
-		in = v.value.Interface()
-	}
-
-	return in, nil
+	return EnsureRawAny(in), nil
 }
 
 // EnsureRawValue pack the interface with value, and make sure it's not a ref holder
@@ -236,6 +228,31 @@ func EnsureRawValue(in interface{}) reflect.Value {
 	return reflect.ValueOf(in)
 }
 
+// EnsureRawAny unpack if in is a reflect.Value or a ref holder.
+func EnsureRawAny(in interface{}) interface{} {
+	if v, ok := in.(reflect.Value); ok {
+		if !v.IsValid() {
+			return nil
+		}
+
+		in = v.Interface()
+	}
+
+	if v, ok := in.(*_refHolder); ok {
+		in = v.value
+	}
+
+	if v, ok := in.(reflect.Value); ok {
+		if !v.IsValid() {
+			return nil
+		}
+
+		in = v.Interface()
+	}
+
+	return in
+}
+
 // SetValue set the value to dest.
 // It will auto check the Ptr pack level and unpack/pack to the right level.
 // It make sure success to set value
diff --git a/java_collection.go b/java_collection.go
index 46a5c9f..f9c0ce5 100644
--- a/java_collection.go
+++ b/java_collection.go
@@ -104,10 +104,7 @@ func (d *Decoder) decodeCollection(length int, listTyp string) (interface{}, err
 	if err != nil {
 		return nil, err
 	}
-	listInterface, err := EnsureInterface(list, nil)
-	if err != nil {
-		return nil, err
-	}
+	listInterface := EnsureRawAny(list)
 	listV, listOk := listInterface.([]interface{})
 	if !listOk {
 		return nil, perrors.New("collection deserialize err " + listTyp)
diff --git a/list.go b/list.go
index 0eeef74..c89bc49 100644
--- a/list.go
+++ b/list.go
@@ -428,7 +428,7 @@ func (d *Decoder) readUntypedList(tag byte) (interface{}, error) {
 			}
 			holder.change(aryValue)
 		} else {
-			ary[j] = it
+			ary[j] = EnsureRawAny(it)
 		}
 	}
 


Test patch:
diff --git a/decode_test.go b/decode_test.go
index 0e57f45..9bf0efe 100644
--- a/decode_test.go
+++ b/decode_test.go
@@ -190,3 +190,51 @@ func TestIssue214(t *testing.T) {
 	t.Log(decode)
 	assert.True(t, reflect.DeepEqual(c, decode))
 }
+
+type Issue299Args1 struct {
+	Label string
+	Key   string
+}
+
+func (Issue299Args1) JavaClassName() string {
+	return "com.test.Issue299Args1"
+}
+
+type Issue299MockData struct {
+	Args []interface{}
+}
+
+func (Issue299MockData) JavaClassName() string {
+	return "com.test.Issue299MockData"
+}
+
+func TestIssue299HessianDecode(t *testing.T) {
+	RegisterPOJO(new(Issue299Args1))
+	RegisterPOJO(new(Issue299MockData))
+
+	d := &Issue299MockData{
+		Args: []interface{}{
+			[]*Issue299Args1{
+				{Label: "1", Key: "2"},
+			},
+		},
+	}
+
+	encoder := NewEncoder()
+	err := encoder.Encode(d)
+	if err != nil {
+		t.Errorf("encode obj error: %v", err)
+		return
+	}
+	decoder := NewDecoder(encoder.Buffer())
+	doInterface, err := decoder.Decode()
+	if err != nil {
+		t.Errorf("decode obj error: %v", err)
+		return
+	}
+	do := doInterface.(*Issue299MockData)
+	if !reflect.DeepEqual(d, do) {
+		t.Errorf("not equal d: %+v, do: %+v", d, do)
+		return
+	}
+}
diff --git a/hessian_test.go b/hessian_test.go
index 9ee1469..a65c61f 100644
--- a/hessian_test.go
+++ b/hessian_test.go
@@ -106,8 +106,8 @@ func doTestResponse(t *testing.T, packageType PackageType, responseStatus byte,
 		return
 	}
 
-	in, _ := EnsureInterface(UnpackPtrValue(EnsurePackValue(body)), nil)
-	out, _ := EnsureInterface(UnpackPtrValue(EnsurePackValue(decodedResponse.RspObj)), nil)
+	in := EnsureRawAny(UnpackPtrValue(EnsurePackValue(body)))
+	out := EnsureRawAny(UnpackPtrValue(EnsurePackValue(decodedResponse.RspObj)))
 	assert.Equal(t, in, out)
 }
 
diff --git a/hessian_test/dup_struct_name_test.go b/hessian_test/dup_struct_name_test.go
index 0c34d44..14a0666 100644
--- a/hessian_test/dup_struct_name_test.go
+++ b/hessian_test/dup_struct_name_test.go
@@ -177,8 +177,8 @@ func checkResponseBody(t *testing.T, decodedResponse *hessian.Response, h *hessi
 		return
 	}
 
-	in, _ := hessian.EnsureInterface(hessian.UnpackPtrValue(hessian.EnsurePackValue(body)), nil)
-	out, _ := hessian.EnsureInterface(hessian.UnpackPtrValue(hessian.EnsurePackValue(decodedResponse.RspObj)), nil)
+	in := hessian.EnsureRawAny(hessian.UnpackPtrValue(hessian.EnsurePackValue(body)))
+	out := hessian.EnsureRawAny(hessian.UnpackPtrValue(hessian.EnsurePackValue(decodedResponse.RspObj)))
 	assert.Equal(t, in, out)
 }