lolly/gjson/types.go
xfy 376b9fd33c feat(gjson): add Lua JSON encoding/decoding library
Add gjson package providing high-performance JSON encoding/decoding
for gopher-lua with lua-cjson API compatibility. Uses goccy/go-json
as the underlying JSON engine.

Features:
- Full lua-cjson API compatibility for OpenResty migration
- Sparse array detection and handling
- Maximum nesting depth control for encode/decode
- Number precision control
- Independent configuration instances via gjson.new()
- gjson.null sentinel for JSON null values

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 15:44:31 +08:00

64 lines
1.8 KiB
Go

package gjson
import (
glua "github.com/yuin/gopher-lua"
)
// nullMarker is a sentinel type to identify gjson.null values.
type nullMarker struct{}
// GJSON represents a gjson instance with its own configuration.
type GJSON struct {
config *Config
null *glua.LUserData
}
// createNull creates the gjson.null lightuserdata for the given LState.
func createNull(L *glua.LState) *glua.LUserData {
ud := L.NewUserData()
ud.Value = nullMarker{}
return ud
}
// isNull checks if a Lua value is gjson.null.
func isNull(value glua.LValue) bool {
if ud, ok := value.(*glua.LUserData); ok {
_, isNullMarker := ud.Value.(nullMarker)
return isNullMarker
}
return false
}
// gjsonNew creates a new GJSON instance with independent configuration.
// Lua: gjson.new() -> new_instance
func gjsonNew(L *glua.LState) int {
// Create new instance with default config
instance := &GJSON{
config: defaultConfig(),
}
instance.null = createNull(L)
// Create instance table
tbl := L.NewTable()
// Register methods (bound to this instance)
L.SetField(tbl, "encode", L.NewFunction(instance.encode))
L.SetField(tbl, "decode", L.NewFunction(instance.decode))
L.SetField(tbl, "encode_sparse_array", L.NewFunction(instance.cfgEncodeSparseArray))
L.SetField(tbl, "encode_max_depth", L.NewFunction(instance.cfgEncodeMaxDepth))
L.SetField(tbl, "decode_max_depth", L.NewFunction(instance.cfgDecodeMaxDepth))
L.SetField(tbl, "encode_number_precision", L.NewFunction(instance.cfgEncodeNumberPrecision))
L.SetField(tbl, "encode_keep_buffer", L.NewFunction(instance.cfgEncodeKeepBuffer))
L.SetField(tbl, "new", L.NewFunction(gjsonNew))
// Set null
L.SetField(tbl, "null", instance.null)
// Set metadata
L.SetField(tbl, "_NAME", glua.LString(ModuleName))
L.SetField(tbl, "_VERSION", glua.LString(Version))
L.Push(tbl)
return 1
}