fix error when convert empty lua table
Signed-off-by: yingjinhui <yingjinhui@didiglobal.com>
This commit is contained in:
parent
aeac17b77d
commit
5cc6d813ab
|
@ -16,6 +16,60 @@ func ConvertLuaResultInto(luaResult lua.LValue, obj interface{}) error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("obj is not pointer")
|
||||
}
|
||||
|
||||
// For example, `GetReplicas` returns requirement with empty:
|
||||
// {
|
||||
// nodeClaim: {},
|
||||
// resourceRequest: {
|
||||
// cpu: "100m"
|
||||
// }
|
||||
// }
|
||||
// Luajson encodes it to
|
||||
// {"nodeClaim": [], "resourceRequest": {"cpu": "100m"}}
|
||||
//
|
||||
// While go json fails to unmarshal `[]` to ReplicaRequirements.NodeClaim object.
|
||||
// ReplicaRequirements object.
|
||||
//
|
||||
// Here we handle it as follows:
|
||||
// 1. Walk the object (lua table), delete the key with empty value (`nodeClaim` in this example):
|
||||
// {
|
||||
// resourceRequest: {
|
||||
// cpu: "100m"
|
||||
// }
|
||||
// }
|
||||
// 2. Encode the object with luajson to be:
|
||||
// {"resourceRequest": {"cpu": "100m"}}
|
||||
// 4. Finally, unmarshal the new json to object, get
|
||||
// {
|
||||
// resourceRequest: {
|
||||
// cpu: "100m"
|
||||
// }
|
||||
// }
|
||||
isEmptyDic := func(v *lua.LTable) bool {
|
||||
count := 0
|
||||
v.ForEach(func(lua.LValue, lua.LValue) {
|
||||
count++
|
||||
})
|
||||
return count == 0
|
||||
}
|
||||
|
||||
var walkValue func(v lua.LValue)
|
||||
walkValue = func(v lua.LValue) {
|
||||
if t, ok := v.(*lua.LTable); ok {
|
||||
t.ForEach(func(key lua.LValue, value lua.LValue) {
|
||||
if tt, ok := value.(*lua.LTable); ok {
|
||||
if isEmptyDic(tt) {
|
||||
// set nil to delete key
|
||||
t.RawSetH(key, lua.LNil)
|
||||
} else {
|
||||
walkValue(value)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
walkValue(luaResult)
|
||||
|
||||
jsonBytes, err := luajson.Encode(luaResult)
|
||||
if err != nil {
|
||||
return fmt.Errorf("json Encode obj eroor %v", err)
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
package luavm
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
)
|
||||
|
||||
func TestConvertLuaResultInto(t *testing.T) {
|
||||
type barStruct struct {
|
||||
Bar string
|
||||
}
|
||||
type fooStruct struct {
|
||||
Bar barStruct
|
||||
}
|
||||
|
||||
type args struct {
|
||||
luaResult lua.LValue
|
||||
obj interface{}
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
want interface{}
|
||||
}{
|
||||
{
|
||||
name: "not a pointer",
|
||||
args: args{
|
||||
luaResult: &lua.LTable{},
|
||||
obj: struct{}{},
|
||||
},
|
||||
wantErr: true,
|
||||
want: struct{}{},
|
||||
},
|
||||
{
|
||||
name: "empty table into struct",
|
||||
args: args{
|
||||
luaResult: &lua.LTable{},
|
||||
obj: &fooStruct{},
|
||||
},
|
||||
wantErr: false,
|
||||
want: &fooStruct{},
|
||||
},
|
||||
{
|
||||
name: "empty table into slice",
|
||||
args: args{
|
||||
luaResult: &lua.LTable{},
|
||||
obj: &[]string{},
|
||||
},
|
||||
wantErr: false,
|
||||
want: &[]string{},
|
||||
},
|
||||
{
|
||||
name: "non-empty table into slice",
|
||||
args: args{
|
||||
luaResult: func() lua.LValue {
|
||||
v := &lua.LTable{}
|
||||
v.Append(lua.LString("foo"))
|
||||
v.Append(lua.LString("bar"))
|
||||
return v
|
||||
}(),
|
||||
obj: &[]string{},
|
||||
},
|
||||
wantErr: false,
|
||||
want: &[]string{"foo", "bar"},
|
||||
},
|
||||
{
|
||||
name: "table with empty table into slice",
|
||||
args: args{
|
||||
luaResult: func() lua.LValue {
|
||||
v := &lua.LTable{}
|
||||
v.RawSetString("Bar", &lua.LTable{})
|
||||
return v
|
||||
}(),
|
||||
obj: &fooStruct{},
|
||||
},
|
||||
wantErr: false,
|
||||
want: &fooStruct{},
|
||||
},
|
||||
{
|
||||
name: "struct is not empty, and convert successfully",
|
||||
args: args{
|
||||
luaResult: func() lua.LValue {
|
||||
bar := &lua.LTable{}
|
||||
bar.RawSetString("Bar", lua.LString("bar"))
|
||||
|
||||
v := &lua.LTable{}
|
||||
v.RawSetString("Bar", bar)
|
||||
return v
|
||||
}(),
|
||||
obj: &fooStruct{},
|
||||
},
|
||||
wantErr: false,
|
||||
want: &fooStruct{
|
||||
Bar: barStruct{Bar: "bar"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := ConvertLuaResultInto(tt.args.luaResult, tt.args.obj); (err != nil) != tt.wantErr {
|
||||
t.Errorf("ConvertLuaResultInto() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
if got := tt.args.obj; !reflect.DeepEqual(tt.want, got) {
|
||||
t.Errorf("ConvertLuaResultInto() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue