171 lines
3.9 KiB
Lua

-- modules/json.lua - High-performance JSON module using Go functions
local json = {}
-- Use the fast Go JSON encoder/decoder
function json.encode(value)
return moonshark.json_encode(value)
end
function json.decode(str)
local result, err = moonshark.json_decode(str)
if result == nil and err then
error("json_decode: " .. err)
end
return result
end
-- Pretty print JSON with indentation
function json.pretty(value, indent)
indent = indent or 2
local encoded = json.encode(value)
local result = {}
local depth = 0
local in_string = false
local escape_next = false
for i = 1, #encoded do
local char = encoded:sub(i, i)
if escape_next then
table.insert(result, char)
escape_next = false
elseif char == "\\" and in_string then
table.insert(result, char)
escape_next = true
elseif char == '"' then
table.insert(result, char)
in_string = not in_string
elseif not in_string then
if char == "{" or char == "[" then
table.insert(result, char)
depth = depth + 1
table.insert(result, "\n" .. string.rep(" ", depth * indent))
elseif char == "}" or char == "]" then
depth = depth - 1
table.insert(result, "\n" .. string.rep(" ", depth * indent))
table.insert(result, char)
elseif char == "," then
table.insert(result, char)
table.insert(result, "\n" .. string.rep(" ", depth * indent))
elseif char == ":" then
table.insert(result, char .. " ")
else
table.insert(result, char)
end
else
table.insert(result, char)
end
end
return table.concat(result)
end
-- Load JSON from file
function json.load_file(filename)
if not moonshark.file_exists(filename) then
error("File not found: " .. filename)
end
local file = io.open(filename, "r")
if not file then
error("Cannot open file: " .. filename)
end
local content = file:read("*all")
file:close()
return json.decode(content)
end
-- Save data to JSON file
function json.save_file(filename, data, pretty)
local content
if pretty then
content = json.pretty(data)
else
content = json.encode(data)
end
local file = io.open(filename, "w")
if not file then
error("Cannot write to file: " .. filename)
end
file:write(content)
file:close()
end
-- Merge JSON objects
function json.merge(...)
local result = {}
for i = 1, select("#", ...) do
local obj = select(i, ...)
if type(obj) == "table" then
for k, v in pairs(obj) do
result[k] = v
end
end
end
return result
end
-- Extract values by JSONPath-like syntax (simplified)
function json.extract(data, path)
local parts = moonshark.string_split(path, ".")
local current = data
for _, part in ipairs(parts) do
if type(current) ~= "table" then
return nil
end
-- Handle array indices [0], [1], etc.
local array_match = part:match("^%[(%d+)%]$")
if array_match then
local index = tonumber(array_match) + 1 -- Lua is 1-indexed
current = current[index]
else
current = current[part]
end
if current == nil then
return nil
end
end
return current
end
-- Validate JSON structure against schema (basic)
function json.validate(data, schema)
local function validate_value(value, schema_value)
local value_type = type(value)
local schema_type = schema_value.type
if schema_type and value_type ~= schema_type then
return false, "Expected " .. schema_type .. ", got " .. value_type
end
if schema_type == "table" and schema_value.properties then
for prop, prop_schema in pairs(schema_value.properties) do
if schema_value.required and schema_value.required[prop] and value[prop] == nil then
return false, "Missing required property: " .. prop
end
if value[prop] ~= nil then
local valid, err = validate_value(value[prop], prop_schema)
if not valid then
return false, "Property " .. prop .. ": " .. err
end
end
end
end
return true
end
return validate_value(data, schema)
end
return json