lolly/gjson/decode.go
xfy c37364b309 style: format code and modernize loop syntax
- Align struct fields and constants in gjson/config.go
- Add missing newline at EOF in gjson/decode.go
- Remove trailing blank line in gjson/encode.go
- Remove extra blank line in internal/lua/coroutine.go
- Use modern for range syntax in internal/lua/pool.go

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 17:34:59 +08:00

112 lines
2.9 KiB
Go

package gjson
import (
"fmt"
json "github.com/goccy/go-json"
glua "github.com/yuin/gopher-lua"
)
// decodeJSONValue converts a JSON string to a Lua value.
func decodeJSONValue(L *glua.LState, data []byte, config *Config, nullValue *glua.LUserData, depth int) (glua.LValue, error) {
// Parse JSON using go-json
var result interface{}
if err := json.Unmarshal(data, &result); err != nil {
return glua.LNil, fmt.Errorf("JSON parse error: %w", err)
}
return convertToLua(L, result, config, nullValue, depth)
}
// convertToLua converts a Go value (from JSON) to a Lua value.
func convertToLua(L *glua.LState, value interface{}, config *Config, nullValue *glua.LUserData, depth int) (glua.LValue, error) {
if depth > config.decodeMaxDepth {
return glua.LNil, fmt.Errorf("maximum nesting depth %d exceeded", config.decodeMaxDepth)
}
if value == nil {
// JSON null -> gjson.null
return nullValue, nil
}
switch v := value.(type) {
case bool:
return glua.LBool(v), nil
case float64:
// Check if it's actually an integer
if v == float64(int64(v)) {
return glua.LNumber(int64(v)), nil
}
return glua.LNumber(v), nil
case string:
return glua.LString(v), nil
case []interface{}:
return convertArrayToLua(L, v, config, nullValue, depth)
case map[string]interface{}:
return convertObjectToLua(L, v, config, nullValue, depth)
case json.Number:
// Handle UseNumber case - parse the number string
num, err := parseJSONNumber(string(v))
if err != nil {
return glua.LNil, err
}
return num, nil
default:
return glua.LNil, fmt.Errorf("unknown JSON type: %T", value)
}
}
// convertArrayToLua converts a JSON array to a Lua table with integer keys (1-based).
func convertArrayToLua(L *glua.LState, arr []interface{}, config *Config, nullValue *glua.LUserData, depth int) (glua.LValue, error) {
tbl := L.NewTable()
for i, item := range arr {
luaVal, err := convertToLua(L, item, config, nullValue, depth+1)
if err != nil {
return glua.LNil, err
}
// Lua arrays are 1-based
tbl.RawSetInt(i+1, luaVal)
}
return tbl, nil
}
// convertObjectToLua converts a JSON object to a Lua table with string keys.
func convertObjectToLua(L *glua.LState, obj map[string]interface{}, config *Config, nullValue *glua.LUserData, depth int) (glua.LValue, error) {
tbl := L.NewTable()
for key, val := range obj {
luaVal, err := convertToLua(L, val, config, nullValue, depth+1)
if err != nil {
return glua.LNil, err
}
tbl.RawSetString(key, luaVal)
}
return tbl, nil
}
// parseJSONNumber parses a JSON number string to a Lua number.
func parseJSONNumber(s string) (glua.LNumber, error) {
// Try parsing as integer first
var intVal int64
if _, err := fmt.Sscanf(s, "%d", &intVal); err == nil {
return glua.LNumber(intVal), nil
}
// Parse as float
var floatVal float64
if _, err := fmt.Sscanf(s, "%f", &floatVal); err == nil {
return glua.LNumber(floatVal), nil
}
return glua.LNumber(0), fmt.Errorf("invalid number format: %s", s)
}