Files
bjarneo--cliamp/luaplugin/api_json.go
T
wehub-resource-sync ead81af521
CI / go (push) Waiting to run
CI / build (darwin, macos-14) (push) Waiting to run
CI / build (windows, windows-2025) (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Failing after 0s
chore: import upstream snapshot with attribution
2026-07-13 12:31:13 +08:00

101 lines
2.0 KiB
Go

package luaplugin
import (
"encoding/json"
lua "github.com/yuin/gopher-lua"
)
// registerJSONAPI adds cliamp.json.{encode,decode} to the cliamp table.
func registerJSONAPI(L *lua.LState, cliamp *lua.LTable) {
tbl := L.NewTable()
// cliamp.json.decode(str) -> table
L.SetField(tbl, "decode", L.NewFunction(func(L *lua.LState) int {
str := L.CheckString(1)
var v any
if err := json.Unmarshal([]byte(str), &v); err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(err.Error()))
return 2
}
L.Push(jsonToLua(L, v))
return 1
}))
// cliamp.json.encode(table) -> string
L.SetField(tbl, "encode", L.NewFunction(func(L *lua.LState) int {
val := L.Get(1)
goVal := luaToGo(val)
data, err := json.Marshal(goVal)
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(err.Error()))
return 2
}
L.Push(lua.LString(string(data)))
return 1
}))
L.SetField(cliamp, "json", tbl)
}
func jsonToLua(L *lua.LState, v any) lua.LValue {
switch val := v.(type) {
case nil:
return lua.LNil
case bool:
return lua.LBool(val)
case float64:
return lua.LNumber(val)
case string:
return lua.LString(val)
case []any:
tbl := L.NewTable()
for i, item := range val {
tbl.RawSetInt(i+1, jsonToLua(L, item))
}
return tbl
case map[string]any:
tbl := L.NewTable()
for k, item := range val {
tbl.RawSetString(k, jsonToLua(L, item))
}
return tbl
default:
return lua.LNil
}
}
func luaToGo(val lua.LValue) any {
switch v := val.(type) {
case *lua.LNilType:
return nil
case lua.LBool:
return bool(v)
case lua.LNumber:
return float64(v)
case lua.LString:
return string(v)
case *lua.LTable:
// Detect if it's an array (sequential integer keys starting at 1).
maxN := v.MaxN()
if maxN > 0 {
arr := make([]any, 0, maxN)
for i := 1; i <= maxN; i++ {
arr = append(arr, luaToGo(v.RawGetInt(i)))
}
return arr
}
m := make(map[string]any)
v.ForEach(func(key, value lua.LValue) {
if ks, ok := key.(lua.LString); ok {
m[string(ks)] = luaToGo(value)
}
})
return m
default:
return nil
}
}