- 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>
112 lines
2.9 KiB
Go
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)
|
|
}
|