Skip to content
Permalink
Browse files
build class definition from map keys
  • Loading branch information
wongoo committed Jan 18, 2022
1 parent ef1946a commit 15f84302dbee92796df9f75b9f5ade9190b51103
Showing 4 changed files with 107 additions and 3 deletions.
@@ -145,6 +145,16 @@ func testDecodeFrameworkFunc(t *testing.T, method string, expected func(interfac
expected(r)
}

func mustDecodeObject(t *testing.T, b []byte) interface{} {
d := NewDecoder(b)
res, err := d.Decode()
if err != nil {
t.Error(err)
t.FailNow()
}
return res
}

func TestUserDefindeException(t *testing.T) {
expect := &UnknownException{
DetailMessage: "throw UserDefindException",
@@ -227,16 +227,24 @@ func (e *Encoder) EncodeMapClass(m map[string]interface{}) error {
// EncodeMapAsClass encode a map as object of given class name.
func (e *Encoder) EncodeMapAsClass(className string, m map[string]interface{}) error {
idx := e.classIndex(className)

if idx == -1 {
var clsDef *ClassInfo
s, ok := getStructInfo(className)
if !ok {
return perrors.Errorf("no class def found: %s", className)
if ok {
clsDef = pojoRegistry.classInfoList[s.index]
} else {
var err error
clsDef, err = buildMapClassDef(className, m)
if err != nil {
return err
}
}
idx = len(e.classInfoList)
clsDef := pojoRegistry.classInfoList[s.index]
e.classInfoList = append(e.classInfoList, clsDef)
e.buffer = append(e.buffer, clsDef.buffer...)
}

return e.encodeMapAsIndexedClass(idx, m)
}

@@ -248,6 +256,9 @@ func (e *Encoder) EncodeMapAsObject(clsDef *ClassInfo, m map[string]interface{})
if idx == -1 {
idx = len(e.classInfoList)
e.classInfoList = append(e.classInfoList, clsDef)
if len(clsDef.buffer) == 0 {
clsDef.initDefBuffer()
}
e.buffer = append(e.buffer, clsDef.buffer...)
}
return e.encodeMapAsIndexedClass(idx, m)
@@ -321,6 +321,49 @@ func TestDecClassToMap(t *testing.T) {
}
}

func TestEncodeMapToObject(t *testing.T) {
name := &UserName{
FirstName: "John",
LastName: "Doe",
}

RegisterPOJO(name)

// note: the first letter of the keys MUST lowercase.
m := map[string]interface{}{
"firstName": "John",
"lastName": "Doe",
}

e := NewEncoder()
encErr := e.EncodeMapAsClass(name.JavaClassName(), m)
if encErr != nil {
t.Error(encErr)
t.FailNow()
}

res := mustDecodeObject(t, e.Buffer())
assert.True(t, reflect.DeepEqual(name, res))

// note: the map contains the class key.
m = map[string]interface{}{
ClassKey: name.JavaClassName(),
"firstName": "John",
"lastName": "Doe",
}

// try to encode again
e = NewEncoder()
encErr = e.EncodeMapClass(m)
if encErr != nil {
t.Error(encErr)
t.FailNow()
}

res = mustDecodeObject(t, e.Buffer())
assert.True(t, reflect.DeepEqual(name, res))
}

type A0 struct{}

// JavaClassName java fully qualified path
40 pojo.go
@@ -105,6 +105,19 @@ var (
javaEnumType = reflect.TypeOf((*POJOEnum)(nil)).Elem()
)

// initDefBuffer initial the class definition buffer, which can be used repeatedly.
func (c *ClassInfo) initDefBuffer() {
if len(c.buffer) == 0 {
c.buffer = encByte(c.buffer, BC_OBJECT_DEF)
c.buffer = encString(c.buffer, c.javaName)
c.buffer = encInt32(c.buffer, int32(len(c.fieldNameList)))

for _, fieldName := range c.fieldNameList {
c.buffer = encString(c.buffer, fieldName)
}
}
}

// struct parsing
func showPOJORegistry() {
pojoRegistry.Lock()
@@ -436,3 +449,30 @@ func lowerCamelCase(s string) string {
runes[0] = unicode.ToLower(runes[0])
return string(runes)
}

// buildMapClassDef build ClassInfo from map keys.
func buildMapClassDef(javaName string, m map[string]interface{}) (*ClassInfo, error) {
if javaName == "" {
var ok bool
javaName, ok = m[ClassKey].(string)
if !ok {
return nil, perrors.Errorf("no java name to build class info from map: %v", m)
}
}

info := &ClassInfo{javaName: javaName}

_, existClassKey := m[ClassKey]

for fieldName := range m {
if existClassKey && fieldName == ClassKey {
continue
}

info.fieldNameList = append(info.fieldNameList, fieldName)
}

info.initDefBuffer()

return info, nil
}

0 comments on commit 15f8430

Please sign in to comment.