Encoding Module
The encoding module provides functionality to convert Lua data structures into common interchange formats like JSON and XML. This is particularly useful for API integrations, data export, and generating structured documents.
Functions
encoding.json(input)
Converts a Lua table into a JSON string representation.
Parameters:
input(table): Lua table to be encoded into JSON
Returns:
string: JSON string representation of the input tablefalse: On encoding error (e.g., unsupported data types)
Example:
local data = {
name = "John Doe",
age = 30,
skills = {"elixir", "lua", "javascript"},
active = true,
profile = {
company = "Acme Corp",
role = "Developer"
}
}
local json_string = encoding.json(data)
print(json_string)
-- Output: {"name":"John Doe","age":30,"skills":["elixir","lua","javascript"],"active":true,"profile":{"company":"Acme Corp","role":"Developer"}}Supported Data Types:
- Strings, numbers, booleans
- Nested tables (converted to JSON objects/arrays)
- Arrays and mixed arrays
nilvalues are omitted from the output
encoding.xml(input)
Converts a Lua table-of-tuples into an XML string using xml_builder format.
Parameters:
input(table): Lua table in XML tuple format:{tag_name, attributes, children}tag_name(string): XML element tag nameattributes(table): Key-value pairs for XML attributes (can be empty{})children(table): Array of child elements or text content
Returns:
string: XML string representationfalse: On encoding error (e.g., malformed input structure)
Example:
-- Simple XML element
local simple = {"Customer", {}, {"Acme Corp"}}
local xml1 = encoding.xml(simple)
print(xml1)
-- Output: <Customer>Acme Corp</Customer>
-- XML with attributes
local with_attrs = {"JDF", {version = "1.3", type = "Product"}, {"Content"}}
local xml2 = encoding.xml(with_attrs)
print(xml2)
-- Output: <JDF version="1.3" type="Product">Content</JDF>
-- Complex nested XML
local complex = {"Order", {id = "123", status = "pending"}, {
{"Customer", {type = "premium"}, {"John Doe"}},
{"Items", {}, {
{"Item", {sku = "ABC-001", qty = "2"}, {"Widget A"}},
{"Item", {sku = "XYZ-999", qty = "1"}, {"Widget B"}}
}},
{"Total", {currency = "USD"}, {"149.98"}}
}}
local xml3 = encoding.xml(complex)
print(xml3)
-- Output: <Order id="123" status="pending">
-- <Customer type="premium">John Doe</Customer>
-- <Items>
-- <Item sku="ABC-001" qty="2">Widget A</Item>
-- <Item sku="XYZ-999" qty="1">Widget B</Item>
-- </Items>
-- <Total currency="USD">149.98</Total>
-- </Order>XML Structure Format:
{
"ElementName", -- Tag name (required)
{attr1 = "value1"}, -- Attributes table (can be empty {})
{ -- Children array (can be empty {})
"Text content", -- Direct text content
{"ChildTag", {}, {"Child content"}}, -- Nested elements
"More text" -- Mixed content supported
}
}Supported Content Types:
- Text strings
- Numbers (converted to strings)
- Booleans (converted to "true"/"false")
- Nested XML elements (as tuples)
- Mixed content (text and elements)
encoding.decodeJson(input)
Parses a JSON string and converts it into a Lua table.
Parameters:
input(string): JSON string to be decoded
Returns:
table: Lua table representation of the JSON datafalse: On decoding error (e.g., invalid JSON, non-string input)
Example:
local json_str = '{"name":"John Doe","age":30,"skills":["elixir","lua"],"active":true}'
local data = encoding.decodeJson(json_str)
print(data.name) -- Output: John Doe
print(data.age) -- Output: 30
print(data.skills[1]) -- Output: elixir
print(data.active) -- Output: true
-- Handling arrays
local json_array = '["apple","banana","cherry"]'
local fruits = encoding.decodeJson(json_array)
for i, fruit in ipairs(fruits) do
print(i .. ": " .. fruit)
end
-- Output: 1: apple, 2: banana, 3: cherry
-- Handling complex nested structures
local complex_json = '{"user":{"name":"Alice","settings":{"theme":"dark","lang":"en"}},"tags":["admin","user"]}'
local complex_data = encoding.decodeJson(complex_json)
print(complex_data.user.settings.theme) -- Output: darkencoding.encodeBase64(input)
Encodes a string into Base64 format for safe transmission and storage.
Parameters:
input(string): String to be encoded
Returns:
string: Base64 encoded stringfalse: On encoding error (e.g., non-string input)
Example:
local text = "Hello, World!"
local encoded = encoding.encodeBase64(text)
print(encoded) -- Output: SGVsbG8sIFdvcmxkIQ==
-- Encoding binary data or special characters
local special_text = "Special chars: áéíóú, symbols: @#$%^&*()"
local encoded_special = encoding.encodeBase64(special_text)
print(encoded_special) -- Output: Base64 encoded version
-- Encoding data for URL or email transmission
local data_to_send = "User data: " .. encoding.json({id = 123, name = "Test"})
local safe_data = encoding.encodeBase64(data_to_send)
-- Now safe_data can be transmitted via URL parameters or emailencoding.decodeBase64(input)
Decodes a Base64 encoded string back to its original form.
Parameters:
input(string): Base64 encoded string to be decoded
Returns:
string: Decoded original stringfalse: On decoding error (e.g., invalid Base64 format, non-string input)
Example:
local encoded = "SGVsbG8sIFdvcmxkIQ=="
local decoded = encoding.decodeBase64(encoded)
print(decoded) -- Output: Hello, World!
-- Round-trip example
local original = "Test data with special chars: 你好世界"
local encoded = encoding.encodeBase64(original)
local decoded = encoding.decodeBase64(encoded)
print(original == decoded) -- Output: true
-- Decoding data received from external systems
local received_data = "eyJpZCI6MTIzLCJuYW1lIjoiVGVzdCJ9"
local json_data = encoding.decodeBase64(received_data)
local parsed_data = encoding.decodeJson(json_data)
print(parsed_data.name) -- Output: TestIntegration Examples
JSON Data Processing
-- Receiving JSON data from external API
function process_api_response(json_response)
local data = encoding.decodeJson(json_response)
if not data then
print("Error: Failed to parse JSON response")
return false
end
-- Process the data
local processed = {
id = data.id,
processed_at = os.date("%Y-%m-%dT%H:%M:%SZ"),
original_data = data,
status = "processed"
}
-- Return as JSON for storage
return encoding.json(processed)
end
-- Example usage
local api_json = '{"id":123,"name":"Product A","price":29.99}'
local result = process_api_response(api_json)
print(result)Base64 Data Handling
-- Encode sensitive data for secure transmission
function prepare_secure_data(user_data)
local json_data = encoding.json(user_data)
local encoded_data = encoding.encodeBase64(json_data)
return {
payload = encoded_data,
encoding = "base64",
content_type = "application/json"
}
end
-- Decode received secure data
function process_secure_data(secure_payload)
if secure_payload.encoding == "base64" then
local decoded_json = encoding.decodeBase64(secure_payload.payload)
if decoded_json then
return encoding.decodeJson(decoded_json)
end
end
return false
end
-- Example usage
local user = {id = 456, email = "user@example.com", role = "admin"}
local secure = prepare_secure_data(user)
local restored = process_secure_data(secure)
print(restored.email) -- Output: user@example.comCombined Encoding Workflows
-- Process and transform data through multiple encoding stages
function data_pipeline(input_json, output_format)
-- Step 1: Decode input JSON
local data = encoding.decodeJson(input_json)
if not data then
return false, "Invalid input JSON"
end
-- Step 2: Transform data
local transformed = {
processed_at = os.date("%Y-%m-%dT%H:%M:%SZ"),
version = "1.0",
data = data
}
-- Step 3: Output in requested format
if output_format == "json" then
return encoding.json(transformed)
elseif output_format == "base64" then
local json_str = encoding.json(transformed)
return encoding.encodeBase64(json_str)
elseif output_format == "xml" then
-- Convert to XML structure
local xml_data = {"ProcessedData", {
processed_at = transformed.processed_at,
version = transformed.version
}, {
{"OriginalData", {}, {encoding.json(data)}}
}}
return encoding.xml(xml_data)
end
return false, "Unsupported output format"
endJSON for API Responses
-- Prepare data for API response
local api_response = {
status = "success",
data = {
users = {
{id = 1, name = "Alice", active = true},
{id = 2, name = "Bob", active = false}
},
total = 2
},
timestamp = "2024-01-15T10:30:00Z"
}
local json_response = encoding.json(api_response)
-- Send via HTTP or store in databaseXML for Document Generation
-- Generate JDF (Job Definition Format) document
local jdf_doc = {"JDF", {
version = "1.3",
type = "Product",
status = "Waiting",
id = "job_12345"
}, {
{"Customer", {}, {"Print Shop ABC"}},
{"JobID", {}, {"12345"}},
{"NodeInfo", {
class = "Parameter",
id = "NI_Media"
}, {
{"Media", {
dimension = "595.275 841.889",
mediatype = "Paper"
}, {}}
}},
{"ResourcePool", {}, {
{"Component", {
id = "COMP_1",
class = "Quantity"
}, {
{"Bundle", {bundleType = "BoxBundle"}, {}}
}}
}}
}}
local jdf_xml = encoding.xml(jdf_doc)
-- Save to file or send to print systemCombined JSON and XML Processing
-- Convert database result to JSON, then embed in XML report
local db_data = {
report_id = "RPT_001",
data = {
total_jobs = 150,
completed = 142,
failed = 8
}
}
local json_data = encoding.json(db_data)
local xml_report = {"Report", {
format = "json",
generated = "2024-01-15T10:30:00Z"
}, {
{"Title", {}, {"Daily Production Report"}},
{"Data", {type = "application/json"}, {json_data}},
{"Summary", {}, {"Production metrics for today"}}
}}
local final_xml = encoding.xml(xml_report)Database Integration
-- Store structured data as JSON in database
function save_user_preferences(user_id, preferences)
local prefs_json = encoding.json(preferences)
local success, result = database.query(
"main-db",
"INSERT INTO user_preferences (user_id, preferences_json) VALUES (?, ?)",
{user_id, prefs_json}
)
return success
end
-- Generate XML configuration files
function generate_printer_config(printer_settings)
local config_xml = {"PrinterConfig", {
version = "1.0",
printer_id = printer_settings.id
}, {
{"Name", {}, {printer_settings.name}},
{"Driver", {type = printer_settings.driver_type}, {printer_settings.driver_path}},
{"Settings", {}, {
{"Resolution", {}, {tostring(printer_settings.dpi)}},
{"ColorProfile", {}, {printer_settings.color_profile}},
{"PaperSize", {}, {printer_settings.paper_size}}
}}
}}
return encoding.xml(config_xml)
endAPI Response Formatting
-- Format GraphQL data for external API
function format_order_for_api(order_data)
local formatted = {
order_id = order_data.id,
status = order_data.status,
customer = {
name = order_data.customer.name,
email = order_data.customer.email
},
items = {},
totals = {
subtotal = order_data.subtotal,
tax = order_data.tax,
total = order_data.total
}
}
-- Transform items
for _, item in ipairs(order_data.items) do
table.insert(formatted.items, {
sku = item.product.sku,
name = item.product.name,
quantity = item.quantity,
unit_price = item.unit_price,
line_total = item.quantity * item.unit_price
})
end
return encoding.json(formatted)
endConfiguration Management
-- Export system configuration as XML
function export_system_config()
local config = {"SystemConfig", {
exported_at = os.date("%Y-%m-%dT%H:%M:%SZ"),
version = "2.1"
}, {}}
-- Add database connections
local db_config = {"Databases", {}, {}}
for _, db in ipairs(get_database_configs()) do
table.insert(db_config[3], {"Database", {
id = db.id,
type = db.type
}, {
{"Host", {}, {db.host}},
{"Port", {}, {tostring(db.port)}},
{"Name", {}, {db.database_name}}
}})
end
table.insert(config[3], db_config)
-- Add printer configurations
local printer_config = {"Printers", {}, {}}
for _, printer in ipairs(get_printer_configs()) do
table.insert(printer_config[3], {"Printer", {
id = printer.id,
enabled = tostring(printer.enabled)
}, {
{"Name", {}, {printer.name}},
{"Model", {}, {printer.model}},
{"Location", {}, {printer.location}}
}})
end
table.insert(config[3], printer_config)
return encoding.xml(config)
endData Migration
-- Convert legacy data formats
function migrate_legacy_orders(legacy_data)
local migrated_orders = {}
for _, legacy_order in ipairs(legacy_data) do
local modern_order = {
id = legacy_order.order_number,
created_at = legacy_order.date_created,
customer_info = {
name = legacy_order.customer_name,
company = legacy_order.company,
contact = {
email = legacy_order.email,
phone = legacy_order.phone
}
},
order_details = {
items = {},
pricing = {
subtotal = legacy_order.subtotal,
tax_rate = legacy_order.tax_rate,
total = legacy_order.total_amount
}
}
}
-- Convert line items
for _, item in ipairs(legacy_order.line_items) do
table.insert(modern_order.order_details.items, {
product_code = item.sku,
description = item.desc,
quantity = item.qty,
unit_price = item.price
})
end
table.insert(migrated_orders, modern_order)
end
-- Export as JSON for import into new system
return encoding.json({
migration_batch = os.date("%Y%m%d_%H%M%S"),
order_count = #migrated_orders,
orders = migrated_orders
})
endBest Practices
Validate input data before encoding:
luafunction safe_json_encode(data) if type(data) ~= "table" then print("Error: Expected table, got " .. type(data)) return false end local result = encoding.json(data) if not result then print("Error: Failed to encode JSON") return false end return result endHandle encoding failures gracefully:
luafunction encode_with_fallback(data, format) local result = nil if format == "json" then result = encoding.json(data) elseif format == "xml" then result = encoding.xml(data) end if not result then print("Encoding failed, using fallback") return encoding.json({error = "Encoding failed", data_type = type(data)}) end return result endValidate XML structure before encoding:
luafunction validate_xml_tuple(tuple) if type(tuple) ~= "table" or #tuple < 3 then return false, "XML tuple must have 3 elements: {tag, attributes, children}" end local tag, attrs, children = tuple[1], tuple[2], tuple[3] if type(tag) ~= "string" then return false, "Tag name must be a string" end if type(attrs) ~= "table" then return false, "Attributes must be a table" end if type(children) ~= "table" then return false, "Children must be a table" end return true endConsider data size limits:
luafunction safe_encode_large_data(data, max_size) max_size = max_size or 1024 * 1024 -- 1MB default local json_str = encoding.json(data) if not json_str then return false, "Encoding failed" end if #json_str > max_size then return false, "Encoded data exceeds size limit" end return json_str end
Error Handling
- Both functions return
falseon encoding errors - Always check return values before using results
- Errors are logged to the application's logger system
Security
- No special permissions required (encoding is a pure data transformation)
- Input validation prevents malformed structures from causing crashes
- Output is safely escaped and formatted
Performance
- JSON encoding is optimized for common Lua data structures
- XML encoding handles deeply nested structures efficiently
- Consider data size and complexity for performance-critical applications
- Cache encoded results for frequently accessed data