commit | bf06cacc2840f6cfb53a00c6a311126773418894 | [log] [tgz] |
---|---|---|
author | fangyincheng <fangyincheng@sina.com> | Sun Jul 12 23:00:07 2020 +0800 |
committer | fangyincheng <fangyincheng@sina.com> | Sun Jul 12 23:00:07 2020 +0800 |
tree | 24bf34609bb199a07bd420ed6f2bfa66b731d139 | |
parent | 707fde85027982890ab8813fae8315d560b110b4 [diff] | |
parent | 44192c6dd28fff48a2ad5d18de700c586427d7df [diff] |
Merge remote-tracking branch 'apache/master' into 1.6
Notice: When decoding, the java version of hessian will default skip and ignore non-exist fields. From the version of v1.6.0 , dubbo-go-hessian2 will skip non-exist fields too, while that before v1.6.0 will return errors.
It's a golang hessian library used by Apache/dubbo-go.
There is a big performance improvement, and some bugs fix for v1.6.0, thanks to micln, pantianying, zonghaishang, willson-chen, champly.
Cross languages message definition should be careful, the following situations should be avoided:
So we can maintain a cross language type mapping:
hessian type | java type | golang type |
---|---|---|
null | null | nil |
binary | byte[] | []byte |
boolean | boolean | bool |
date | java.util.Date | time.Time |
double | double | float64 |
int | int | int32 |
long | long | int64 |
string | java.lang.String | string |
list | java.util.List | slice |
map | java.util.Map | map |
object | custom define object | custom define struct |
OTHER COMMON USING TYPE | ||
big decimal | java.math.BigDecimal | github.com/dubbogo/gost/math/big/Decimal |
big integer | java.math.BigInteger | github.com/dubbogo/gost/math/big/Integer |
type Circular struct {
Value
Previous *Circular
Next *Circular
}
type Value struct {
Num int
}
func (Circular) JavaClassName() string {
return "com.company.Circular"
}
c := &Circular{}
c.Num = 12345
c.Previous = c
c.Next = c
e := NewEncoder()
err := e.Encode(c)
if err != nil {
panic(err)
}
bytes := e.Buffer()
decodedObject, err := NewDecoder(bytes).Decode() if err != nil { panic(err) } circular, ok := obj.(*Circular) // ...
Hessian encoder default converts filed names of struct to lower camelcase, but you can customize it using hessian
tag.
Example:
type MyUser struct { UserFullName string `hessian:"user_full_name"` FamilyPhoneNumber string // default convert to => familyPhoneNumber } func (MyUser) JavaClassName() string { return "com.company.myuser" } user := &MyUser{ UserFullName: "username", FamilyPhoneNumber: "010-12345678", } e := hessian.NewEncoder() err := e.Encode(user) if err != nil { panic(err) }
The encoded bytes of the struct MyUser
is as following:
00000000 43 12 63 6f 6d 2e 63 6f 6d 70 61 6e 79 2e 6d 79 |C.com.company.my| 00000010 75 73 65 72 92 0e 75 73 65 72 5f 66 75 6c 6c 5f |user..user_full_| 00000020 6e 61 6d 65 11 66 61 6d 69 6c 79 50 68 6f 6e 65 |name.familyPhone| 00000030 4e 75 6d 62 65 72 60 08 75 73 65 72 6e 61 6d 65 |Number`.username| 00000040 0c 30 31 30 2d 31 32 33 34 35 36 37 38 |.010-12345678|
Hessian decoder finds the correct target field though comparing all filed names of struct one by one until matching.
The following example shows the order of the matching rules:
type MyUser struct { MobilePhone string `hessian:"mobile-phone"` } // You must define the tag of struct for lookup filed form encoded binary bytes, in this caseļ¼ // 00000000 43 12 63 6f 6d 2e 63 6f 6d 70 61 6e 79 2e 6d 79 |C.com.company.my| // 00000010 75 73 65 72 91 0c 6d 6f 62 69 6c 65 2d 70 68 6f |user..mobile-pho| // 00000020 6e 65 60 0b 31 37 36 31 32 33 34 31 32 33 34 |ne`.17612341234| // // mobile-phone(tag lookup) => mobilePhone(lowerCameCase) => MobilePhone(SameCase) => mobilephone(lowercase) // ^ will matched type MyUser struct { MobilePhone string } // The following encoded binary bytes will be hit automatically: // // 00000000 43 12 63 6f 6d 2e 63 6f 6d 70 61 6e 79 2e 6d 79 |C.com.company.my| // 00000010 75 73 65 72 91 0b 6d 6f 62 69 6c 65 50 68 6f 6e |user..mobilePhon| // 00000020 65 60 0b 31 37 36 31 32 33 34 31 32 33 34 |e`.17612341234| // // mobile-phone(tag lookup) => mobilePhone(lowerCameCase) => MobilePhone(SameCase) => mobilephone(lowercase) // ^ will matched // // 00000000 43 12 63 6f 6d 2e 63 6f 6d 70 61 6e 79 2e 6d 79 |C.com.company.my| // 00000010 75 73 65 72 91 0b 4d 6f 62 69 6c 65 50 68 6f 6e |user..MobilePhon| // 00000020 65 60 0b 31 37 36 31 32 33 34 31 32 33 34 |e`.17612341234| // // mobile-phone(tag lookup) => mobilePhone(lowerCameCase) => MobilePhone(SameCase) => mobilephone(lowercase) // ^ will matched // // 00000000 43 12 63 6f 6d 2e 63 6f 6d 70 61 6e 79 2e 6d 79 |C.com.company.my| // 00000010 75 73 65 72 91 0b 6d 6f 62 69 6c 65 70 68 6f 6e |user..mobilephon| // 00000020 65 60 0b 31 37 36 31 32 33 34 31 32 33 34 |e`.17612341234| // // mobile-phone(tag lookup) => mobilePhone(lowerCameCase) => MobilePhone(SameCase) => mobilephone(lowercase) // ^ will matched
You can use hessian.SetTagIdentifier
to customize tag-identifier of hessian, which takes effect to both encoder and decoder.
Example:
hessian.SetTagIdentifier("json") type MyUser struct { UserFullName string `json:"user_full_name"` FamilyPhoneNumber string // default convert to => familyPhoneNumber } func (MyUser) JavaClassName() string { return "com.company.myuser" } user := &MyUser{ UserFullName: "username", FamilyPhoneNumber: "010-12345678", } e := hessian.NewEncoder() err := e.Encode(user) if err != nil { panic(err) }
The encoded bytes of the struct MyUser
is as following:
00000000 43 12 63 6f 6d 2e 63 6f 6d 70 61 6e 79 2e 6d 79 |C.com.company.my| 00000010 75 73 65 72 92 0e 75 73 65 72 5f 66 75 6c 6c 5f |user..user_full_| 00000020 6e 61 6d 65 11 66 61 6d 69 6c 79 50 68 6f 6e 65 |name.familyPhone| 00000030 4e 75 6d 62 65 72 60 08 75 73 65 72 6e 61 6d 65 |Number`.username| 00000040 0c 30 31 30 2d 31 32 33 34 35 36 37 38 |.010-12345678|
By default, the output of Hessian Java impl of a Java collection like java.util.HashSet will be decoded as []interface{}
in go-hessian2
. To apply the one-to-one mapping relationship between certain Java collection class and your Go struct, examples are as follows:
//use HashSet as example //define your struct, which should implements hessian.JavaCollectionObject type JavaHashSet struct { value []interface{} } //get the inside slice value func (j *JavaHashSet) Get() []interface{} { return j.value } //set the inside slice value func (j *JavaHashSet) Set(v []interface{}) { j.value = v } //should be the same as the class name of the Java collection func (j *JavaHashSet) JavaClassName() string { return "java.util.HashSet" } func init() { //register your struct so that hessian can recognized it when encoding and decoding SetCollectionSerialize(&JavaHashSet{}) }
go-hessian2
supports inheritance struct, but the following situations should be avoided.
The following struct C
have inherited field Name
(default from the first parent), but it's confused in logic.
type A struct { Name string }
type B struct { Name string }
type C struct {
A
B
}
The following definition is valid for golang syntax, but the parent will be nil when create a new Dog, like dog := Dog{}
, which will not happen in java inheritance, and is also not supported by go-hessian2
.
type Dog struct {
*Animal
}