in object.go [107:217]
func (e *Encoder) encObject(v interface{}) error {
var (
i int
idx int
num int
err error
clsDef *ClassInfo
)
pojo, isPojo := v.(POJO)
// get none pojo JavaClassName
var nonePojoJavaName string
if !isPojo {
s, ok := loadPOJORegistry(v)
if !ok {
return perrors.Errorf("non-pojo obj %s has not being registered before!", typeof(v))
}
nonePojoJavaName = s.javaName
}
vv := reflect.ValueOf(v)
// check ref
if n, ok := e.checkRefMap(vv); ok {
e.buffer = encRef(e.buffer, n)
return nil
}
vv = UnpackPtr(vv)
// check nil pointer
if !vv.IsValid() {
e.buffer = EncNull(e.buffer)
return nil
}
// write object definition
idx = -1
for i = range e.classInfoList {
if isPojo && pojo.JavaClassName() == e.classInfoList[i].javaName || !isPojo && nonePojoJavaName == e.classInfoList[i].javaName {
idx = i
break
}
}
var ok bool
if idx == -1 {
idx, ok = checkPOJORegistry(v)
if !ok {
if reflect.TypeOf(v).Implements(javaEnumType) {
idx = RegisterJavaEnum(v.(POJOEnum))
} else if isPojo {
idx = RegisterPOJO(pojo)
} else {
return perrors.Errorf("non-pojo obj %s has not being registered before!", typeof(v))
}
}
_, clsDef, err = getStructDefByIndex(idx)
if err != nil {
return perrors.WithStack(err)
}
idx = len(e.classInfoList)
e.classInfoList = append(e.classInfoList, clsDef)
e.buffer = append(e.buffer, clsDef.buffer...)
}
// write object instance
if byte(idx) <= OBJECT_DIRECT_MAX {
e.buffer = encByte(e.buffer, byte(idx)+BC_OBJECT_DIRECT)
} else {
e.buffer = encByte(e.buffer, BC_OBJECT)
e.buffer = encInt32(e.buffer, int32(idx))
}
if reflect.TypeOf(v).Implements(javaEnumType) {
e.buffer = encString(e.buffer, v.(POJOEnum).String())
return nil
}
structs := []reflect.Value{vv}
for len(structs) > 0 {
vv := structs[0]
vvt := vv.Type()
num = vv.NumField()
for i = 0; i < num; i++ {
tf := vvt.Field(i)
// skip unexported anonymous field
if tf.PkgPath != "" {
continue
}
// skip ignored field
if tag, _ := tf.Tag.Lookup(tagIdentifier); tag == `-` {
continue
}
field := vv.Field(i)
if tf.Anonymous && field.Kind() == reflect.Struct {
structs = append(structs, field)
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
}