Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于对 Java Collection 的支持 #122

Closed
YGrylls opened this issue Aug 28, 2019 · 1 comment
Closed

关于对 Java Collection 的支持 #122

YGrylls opened this issue Aug 28, 2019 · 1 comment

Comments

@YGrylls
Copy link
Contributor

YGrylls commented Aug 28, 2019

与 Java 对接业务中(尤其指对接已有 Java 端)可能遇到 Java 端出于某些原因需要接收非 List 类型集合的情况,如 Set 等。
可以考虑加入对 Java Collection 的序列化与反序列化支持。

Java 端 hessian 序列化非 List 类型集合是序列化成 fixed-length type list 的形式,集合的类型被写在 type 中的一部分。见 com.caucho.hessian.io.CollectionSerializer .

模仿 Java 序列化的方式目前可以通过 go-hessian 的 Serializer 扩展加一个 JavaCollection 接口的形式提供序列化集合的功能(代码见下方),但接收 Java 端集合的情况下,所有集合(被序列化为 fixed-length type list)都会因为头部是 list ('v' 或者 0x70 - 0x77)被 declist 方法反序列化为切片而无法经过 Serializer 提供的反序列化方法(decode.go#line 199 ),可能无法满足两端对象一一对应的业务需求。(即:可以满足发送特定Collection的需求,但无法还原)

可能的解决方案:

对 decode 进行一定的修改,使反序列化对象为 list 的时候,type 也作为选择 dec 方法的依据,
从而让特定 Collection 的反序列化经过 Java Collection 的反序列化器

↓ 一种基于 Serializer 扩展的序列化方案(不包含反序列化)

type JavaCollectionObject interface {
	Get() []interface{}
	JavaClassName() string
}

func init() {
	hessian.SetSerializer("java.util.HashSet", JavaCollectionSerializer{})
}

type JavaCollectionSerializer struct {
}

func (JavaCollectionSerializer) EncObject(e *hessian.Encoder, vv hessian.POJO) error {
	var (
		err error
	)
	v, ok := vv.(JavaCollectionObject)
	if !ok {
		return perrors.New("can not be converted into java collection object")
	}
	collectionName := v.JavaClassName()
	if collectionName == "" {
		return perrors.New("collection name empty")
	}
	list := v.Get()
	length := len(list)
	typeName := v.JavaClassName()
	err = writeCollectionBegin(length, typeName, e)
	if err != nil {
		return err
	}
	for i := 0; i < length; i++ {
		if err = e.Encode(list[i]); err != nil {
			return err
		}
	}
	return nil

}

func (JavaCollectionSerializer) DecObject(d *hessian.Decoder) (interface{}, error) {
	//For collections are coded as lists instead of objects, so the dec method will never be invoked
	return nil, nil
}

func writeCollectionBegin(length int, typeName string, e *hessian.Encoder) error {
	var err error
	if length <= int(hessian.LIST_DIRECT_MAX) {
		e.Append([]byte{hessian.BC_LIST_DIRECT + byte(length)})
		err = e.Encode(typeName)
		if err != nil {
			return err
		}
	} else {
		e.Append([]byte{hessian.BC_LIST_FIXED})
		err = e.Encode(typeName)
		if err != nil {
			return err
		}
		err = e.Encode(int32(length))
		if err != nil {
			return nil
		}
	}
	return nil
} 
@wongoo
Copy link
Contributor

wongoo commented Feb 24, 2020

a PR is welcome

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants