Skip to content

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 table
  • false: On encoding error (e.g., unsupported data types)

Example:

lua
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
  • nil values 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 name
    • attributes (table): Key-value pairs for XML attributes (can be empty {})
    • children (table): Array of child elements or text content

Returns:

  • string: XML string representation
  • false: On encoding error (e.g., malformed input structure)

Example:

lua
-- 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:

lua
{
    "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 data
  • false: On decoding error (e.g., invalid JSON, non-string input)

Example:

lua
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: dark

encoding.encodeBase64(input)

Encodes a string into Base64 format for safe transmission and storage.

Parameters:

  • input (string): String to be encoded

Returns:

  • string: Base64 encoded string
  • false: On encoding error (e.g., non-string input)

Example:

lua
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 email

encoding.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 string
  • false: On decoding error (e.g., invalid Base64 format, non-string input)

Example:

lua
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: Test

Integration Examples

JSON Data Processing

lua
-- 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

lua
-- 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.com

Combined Encoding Workflows

lua
-- 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"
end

JSON for API Responses

lua
-- 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 database

XML for Document Generation

lua
-- 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 system

Combined JSON and XML Processing

lua
-- 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

lua
-- 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)
end

API Response Formatting

lua
-- 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)
end

Configuration Management

lua
-- 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)
end

Data Migration

lua
-- 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
    })
end

Best Practices

  1. Validate input data before encoding:

    lua
    function 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
    end
  2. Handle encoding failures gracefully:

    lua
    function 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
    end
  3. Validate XML structure before encoding:

    lua
    function 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
    end
  4. Consider data size limits:

    lua
    function 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 false on 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

Connect. Combine. Collaborate.
The pioneering open integration platform, dedicated to transforming connectivity in the printing industry.