Overview
Lutaml::Model is a modelling library that provides a rich superset of features compared to Shale, including enhanced XML and JSON serialization capabilities, better namespace management, and more.
Step 1: Replace inheritance class
Lutaml::Model uses Lutaml::Model::Serializable as the base inheritance class.
class Example < Lutaml::Model::Serializable
# ...
end|
|
Shale uses Shale::Mapper as the base inheritance class.
class Example < Shale::Mapper
# ...
endActions:
-
Replace mentions of
Shale::MapperwithLutaml::Model::Serializable. -
Potentially replace inheritance with inclusion for suitable cases.
Step 2: Replace value type definitions
Value types in Lutaml::Model are under the Lutaml::Model::Type module, or use the LutaML type symbols.
class Example < Lutaml::Model::Serializable
attribute :length, :integer
attribute :description, :string
end|
|
Value types in Shale are under the Shale::Type module.
class Example < Shale::Mapper
attribute :length, Shale::Type::Integer
attribute :description, Shale::Type::String
endAction:
-
Replace mentions of
Shale::TypewithLutaml::Model::Type. -
Potentially replace value type definitions with strings or symbols.
Step 3: Configure serialization adapters
Lutaml::Model uses a configuration block to set the serialization adapters.
require 'lutaml/model/xml/nokogiri_adapter'
Lutaml::Model::Config.configure do |config|
config.xml_adapter = Lutaml::Model::Xml::NokogiriAdapter
endThe equivalent for Shale is this:
require 'shale/adapter/nokogiri'
Shale.xml_adapter = Shale::Adapter::Nokogiri Lutaml::Model::XmlAdapter is deprecated and will be removed in the next major upgrade. Use Lutaml::Model::Xml instead. |
Here are places that this code may reside at:
-
If your code is a standalone Ruby script, this code will be present in your code.
-
If your code is organized in a Ruby gem, this code will be specified somewhere referenced by
lib/your_gem_name.rb. -
If your code contains tests or specs, they will be in the test setup file, e.g. RSpec
spec/spec_helper.rb.
Actions:
-
Replace the Shale configuration block with the
Lutaml::Model::Configconfiguration block. -
Replace the Shale adapter with the
Lutaml::Modeladapter.
Step 4: Rewrite custom serialization methods
There is an implementation difference between Lutaml::Model and Shale for custom serialization methods.
Custom serialization methods in Lutaml::Model map to individual attributes.
For custom serialization methods, Lutaml::Model uses the :with keyword instead of the :using keyword used by Shale.
class Example < Lutaml::Model::Serializable
attribute :name, :string
attribute :size, :integer
attribute :color, :string
attribute :description, :string
json do
map "name", to: :name, with: { to: :name_to_json, from: :name_from_json }
map "size", to: :size
map "color", to: :color,
with: { to: :color_to_json, from: :color_from_json }
map "description", to: :description,
with: { to: :description_to_json, from: :description_from_json }
end
xml do
root "CustomSerialization"
map_element "Name", to: :name,
with: { to: :name_to_xml, from: :name_from_xml }
map_attribute "Size", to: :size
map_element "Color", to: :color,
with: { to: :color_to_xml, from: :color_from_xml }
map_content to: :description,
with: { to: :description_to_xml,
from: :description_from_xml }
end
def name_to_json(model, doc)
doc["name"] = "JSON Masterpiece: #{model.name}"
end
def name_from_json(model, value)
model.name = value.sub(/^JSON Masterpiece: /, "")
end
def color_to_json(model, doc)
doc["color"] = model.color.upcase
end
def color_from_json(model, value)
model.color = value.downcase
end
def description_to_json(model, doc)
doc["description"] = "JSON Description: #{model.description}"
end
def description_from_json(model, value)
model.description = value.sub(/^JSON Description: /, "")
end
def name_to_xml(model, parent, doc)
el = doc.create_element("Name")
doc.add_text(el, "XML Masterpiece: #{model.name}")
doc.add_element(parent, el)
end
def name_from_xml(model, value)
model.name = value.sub(/^XML Masterpiece: /, "")
end
def color_to_xml(model, parent, doc)
color_element = doc.create_element("Color")
doc.add_text(color_element, model.color.upcase)
doc.add_element(parent, color_element)
end
def color_from_xml(model, value)
model.color = value.downcase
end
def description_to_xml(model, parent, doc)
doc.add_text(parent, "XML Description: #{model.description}")
end
def description_from_xml(model, value)
model.description = value.join.strip.sub(/^XML Description: /, "")
end
endCustom serialization methods in Shale do not map to specific attributes, but allow the user to specify where the data goes.
class Example < Shale::Mapper
attribute :name, Shale::Type::String
attribute :size, Shale::Type::Integer
attribute :color, Shale::Type::String
attribute :description, Shale::Type::String
json do
map "name", using: { from: :name_from_json, to: :name_to_json }
map "size", to: :size
map "color", using: { from: :color_from_json, to: :color_to_json }
map "description", to: :description, using: { from: :description_from_json, to: :description_to_json }
end
xml do
root "CustomSerialization"
map_element "Name", using: { from: :name_from_xml, to: :name_to_xml }
map_attribute "Size", to: :size
map_element "Color", using: { from: :color_from_xml, to: :color_to_xml }
map_content to: :description, using: { from: :description_from_xml, to: :description_to_xml }
end
def name_to_json(model, doc)
doc['name'] = "JSON Masterpiece: #{model.name}"
end
def name_from_json(model, value)
model.name = value.sub(/^JSON Masterpiece: /, "")
end
def color_to_json(model, doc)
doc['color'] = model.color.upcase
end
def color_from_json(model, doc)
model.color = doc['color'].downcase
end
def description_to_json(model, doc)
doc['description'] = "JSON Description: #{model.description}"
end
def description_from_json(model, doc)
model.description = doc['description'].sub(/^JSON Description: /, "")
end
def name_from_xml(model, node)
model.name = node.text.sub(/^XML Masterpiece: /, "")
end
def name_to_xml(model, parent, doc)
name_element = doc.create_element('Name')
doc.add_text(name_element, model.street.to_s)
doc.add_element(parent, name_element)
end
end| There are cases where the Shale implementation of custom methods work differently from the Lutaml::Model implementation. In these cases, you will need to adjust the custom methods accordingly. |
Actions:
-
Replace the
usingkeyword with thewithkeyword. -
Adjust the custom methods.