apache/dubbo-go-hessian2

go interface decode failed when encounter a generic list object return from java

wangzeping722 opened this issue · 0 comments

dubbo-go-hessian2 version: v1.9.2

What happened:
I hava java object like blow:

public class Response<T> implements Serializable {

    private int code;
    private T data;

    public int getCode() {
        return code;
    }

    public T getData() {
        return data;
    }

    public Response(int code, T data) {
        this.code = code;
        this.data = data;
    }
}

public class BusinessData implements Serializable {

    private String name;
    private int count;

    public BusinessData() {
    }

    public BusinessData(String name, int count) {
        this.name = name;
        this.count = count;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

T is List<BusinessData>.

And, i hava go struct like below:

type GenericResponse struct {
	Code int
	Data interface{}
}

type BusinessData struct {
	Name  string
	Count int
}

When i use GenericResponse to decode the response returned from java which is a Response<List<BusinessData>> contains one element, but the field GenericResponse.Data is nil.

What you expected to happen:

It should not be nil, but a []interface with one element.

How to reproduce it (as minimally and precisely as possible):

Modify the test case TestCustomReplyGenericResponseBusinessData:

func TestCustomReplyGenericResponseBusinessData(t *testing.T) {
	//data := BusinessData{
	//	Name:  "apple",
	//	Count: 5,
	//}
	res := &GenericResponse{
		Code: 201,
		Data: []interface{}{
			&BusinessData{
				Name:  "apple",
				Count: 5,
			},
		},
	}
	RegisterPOJO(&BusinessData{})
	RegisterPOJO(res)

	testDecodeFramework(t, "customReplyGenericResponseBusinessData", res)
}

and modify test data customReplyGenericResponseBusinessData:

public void customReplyGenericResponseBusinessData() throws Exception {
    List<BusinessData> list = new ArrayList<>();
    list.add(new BusinessData("apple", 5));
    Response<List<BusinessData>> response = new Response<>(201, list);
    output.writeObject(response);
    output.flush();
}

Run test case, it will reproduce:

=== RUN TestCustomReplyGenericResponseBusinessData
2021/06/23 10:16:29 get java reply: customReplyGenericResponseBusinessData
decode_test.go:130: customReplyGenericResponseBusinessData: got &{201 }, wanted &{201 [0xc0001a0168]}
--- FAIL: TestCustomReplyGenericResponseBusinessData (0.85s)

FAIL

Anything else we need to know?:

I modify the code in codec.go , func SetValue, it can pass test. but i hava few experience with hessian2, so i don't think it can work well.

	// check whether the v is a ref holder
	if v.IsValid() {
		if h, ok := v.Interface().(*_refHolder); ok {
			if h.value.Kind() != reflect.Slice {
				h.add(dest)
				return
			} else {
				dest.Set(h.value)
				return
			}
		}
	}