Overview
Lutaml::Model uses an adapter pattern to support multiple serialization libraries. Adapters are resolved automatically via lazy auto-detection, but can be explicitly configured when needed.
Auto-detection
Lutaml::Model automatically detects available adapter gems at runtime on first use. You only need to configure adapters if:
-
You want to override the default choice
-
You are testing and need deterministic adapter selection
-
Your library requires a specific adapter
The auto-detection order for each format:
| Format | Detection order |
|---|---|
XML |
|
TOML |
|
JSON |
|
YAML |
|
Hash |
|
Basic configuration
Use Lutaml::Model::Config.configure to set adapters:
require 'lutaml/model'
Lutaml::Model::Config.configure do |config|
config.xml_adapter = :nokogiri
config.json_adapter = :standard
config.yaml_adapter = :standard
config.toml_adapter = :toml_rb
config.hash_adapter = :standard
endResolution chain
When an adapter is needed for a format, AdapterResolver follows this chain:
-
Thread-local scope override — from
Config.with_adapterblock -
Explicitly configured type — from
Config.xml_adapter_type = :nokogiri -
Lazy auto-detected type — cached after first probe
-
Format default — built-in default for the format
-
Error —
FormatAdapterNotSpecifiedError
Available adapters
XML adapters
| Adapter | Description |
|---|---|
| Most compatible, based on libxml2. Requires native extensions. |
| Fastest performance. Native C extensions. |
| Pure Ruby. No compilation needed. Opal-compatible. |
| Pure Ruby. Bundled with Ruby (default gem). Opal-compatible. |
JSON adapters
| Adapter | Description |
|---|---|
| Ruby standard library. No extra gems needed. |
| Common interface wrapper for multiple JSON libraries. |
| Fast C-based parser. Excellent performance. |
YAML adapter
| Adapter | Description |
|---|---|
| Psych (Ruby standard library). No extra gems needed. |
TOML adapters
| Adapter | Description |
|---|---|
| Native engine (libteptris via FFI), all platforms including Windows. tomlib-compatible value semantics. |
| Enhanced fork. Better performance on non-Windows platforms. |
| Pure Ruby. TOML v1.0.0 compatible. |
The :tomlib adapter is not available on Windows due to segmentation fault issues. On Windows, :teptris (when bundled) or :toml_rb is used as the default. |
Per-operation adapter override
Override the adapter for a single serialization/deserialization call using the adapter: option:
# Parse with Ox for this call only
model = MyClass.from_xml(xml_string, adapter: :ox)
# Serialize with REXML for this call only
output = model.to_xml(adapter: :rexml)This is useful for:
-
Testing with a specific adapter without changing global configuration
-
Performance-sensitive operations using a faster adapter
-
Cross-adapter workflows (parse with one, serialize with another)
Scoped adapter context
Use Config.with_adapter for thread-safe, block-scoped adapter overrides:
# All XML operations in this block use Ox
Lutaml::Model::Config.with_adapter(xml: :ox) do
model = MyClass.from_xml(data)
model.to_xml # also uses Ox
end
# Outside the block, reverts to the configured default
# Multiple formats at once
Lutaml::Model::Config.with_adapter(xml: :nokogiri, toml: :tomlib) do
model = MyClass.from_xml(data)
toml = model.to_toml
end with_adapter is thread-safe — each thread has its own scope stack. Use it in tests instead of save/restore patterns: |
# Instead of this:
around do |example|
old = Config.xml_adapter
Config.xml_adapter_type = :oga
example.run
ensure
Config.xml_adapter = old
end
# Prefer this:
around do |example|
Config.with_adapter(xml: :oga) { example.run }
endLibrary stacking
When multiple libraries depend on lutaml-model, each can set its preferred adapter within a scoped context:
# In gem "my_xml_library"
module MyXmlLibrary
def self.parse(data)
# This gem requires Nokogiri internally
Config.with_adapter(xml: :nokogiri) do
MyModel.from_xml(data)
end
end
end
# The end-user's adapter choice is not affected
Config.xml_adapter_type = :ox # user prefers Ox
result = MyXmlLibrary.parse(data) # uses Nokogiri inside
my_model.to_xml # uses Ox (user's choice)Configuration with class references
For advanced use, specify adapter classes directly:
require 'lutaml/model'
require 'lutaml/xml/adapter/nokogiri_adapter'
require 'lutaml/key_value/adapter/json/standard_adapter'
require 'lutaml/key_value/adapter/yaml/standard_adapter'
require 'lutaml/toml/adapter/toml_rb_adapter'
Lutaml::Model::Config.configure do |config|
config.xml_adapter = Lutaml::Xml::Adapter::NokogiriAdapter
config.json_adapter = Lutaml::Json::Adapter::StandardAdapter
config.yaml_adapter = Lutaml::Yaml::Adapter::StandardAdapter
config.toml_adapter = Lutaml::Toml::Adapter::TomlRbAdapter
endDefault configuration
If not explicitly configured, Lutaml::Model auto-detects on first use:
-
XML:
:nokogiriif available, else:ox→:oga→:rexml -
JSON:
:standard(alias::standard_json) -
YAML:
:standard(alias::standard_yaml) -
Hash:
:standard(alias::standard_hash) -
TOML:
:teptrisif available, else:tomlibon non-Windows,:toml_rbon Windows
When to configure
Configure adapters in one of these locations:
- For applications
-
In an initializer or early-loading file (optional — auto-detection usually sufficient)
- For gems
-
Do not configure globally. Use
Config.with_adapterfor internal adapter requirements. - For testing
-
In
spec_helper.rbor test setup, or useConfig.with_adapterper test.
# spec/spec_helper.rb
require 'lutaml/model'
Lutaml::Model::Config.configure do |config|
config.xml_adapter = :nokogiri
config.json_adapter = :standard
config.yaml_adapter = :standard
config.toml_adapter = :toml_rb
endAdapter selection guide
Choose XML adapter based on
-
Nokogiri: Most projects (default, best compatibility)
-
Ox: Performance-critical applications
-
Oga: Pure Ruby environments
-
REXML: No extra gems, pure Ruby (bundled with Ruby). Also used under Opal.
Opal runtime compatibility
Lutaml::Model supports running under Opal (Ruby compiled to JavaScript) with some limitations. The library detects the runtime automatically via Lutaml::Model::RuntimeCompatibility and adapts its behavior accordingly.
The XML parsing layer is provided by the moxml gem, which has been updated to support Opal. Under Opal, moxml uses the REXML adapter because Opal reimplements strscan and stringio in its stdlib, enabling REXML (pure Ruby) to compile cleanly to JavaScript.
Adapter defaults on Opal
| Format | Behavior |
|---|---|
XML | Only |
JSON | Only |
YAML |
|
TOML | Not available. Both tomlib and toml-rb depend on native extensions. |
Hash |
|
Features unavailable on Opal
The following features raise NotImplementedError when called under Opal:
-
Lutaml::Model::Schema.to_xsd— XSD schema generation requires Nokogiri -
Lutaml::Model::Schema.to_relaxng— RELAX NG generation requires Nokogiri -
Lutaml::Model::Schema.from_xml— XML schema compilation is not supported -
Lutaml::Xml::Schema::Xsd::Base#to_formatted_xml— XSD formatted output requires the Canon gem -
XPath queries — REXML XPath requires features not yet supported by Opal’s stdlib
See the Opal Usage Guide for complete setup instructions and limitations.