require "spec_helper"
require "lutaml/model"
class CustomSerialization < Lutaml::Model::Serializable
attribute :full_name, :string
attribute :size, :integer
attribute :color, :string
attribute :description, :string
json do
map "name", with: { to: :name_to_json, from: :name_from_json }
map "color", with: { to: :color_to_json, from: :color_from_json }
map "size", with: { to: :size_to_json, from: :size_from_json }
map "description",
with: { to: :description_to_json, from: :description_from_json }
end
xml do
root "CustomSerialization"
# name, color are used to test XML elements with custom methods
map_element "Name", with: { to: :name_to_xml, from: :name_from_xml }
map_element "Color", with: { to: :color_to_xml, from: :color_from_xml }
# size is used to test XML attribute with custom methods
map_attribute "Size", with: { to: :size_to_xml, from: :size_from_xml }
# description is used to test XML textual content
map_content with: { to: :description_to_xml, from: :description_from_xml }
end
def name_to_json(model, doc)
doc["name"] = "JSON Masterpiece: #{model.full_name}"
end
def name_from_json(model, value)
model.full_name = value.sub(/^JSON Masterpiece: /, "")
end
def size_to_json(model, doc)
doc["size"] = model.size + 3
end
def size_from_json(model, value)
model.size = value - 3
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.full_name}")
doc.add_element(parent, el)
end
def name_from_xml(model, value)
model.full_name = value.sub(/^XML Masterpiece: /, "")
end
def size_to_xml(model, parent, doc)
doc.add_attribute(parent, "Size", model.size + 3)
end
def size_from_xml(model, value)
model.size = value.to_i - 3
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
end
RSpec.describe CustomSerialization do
let(:attributes) do
{
full_name: "Vase",
size: 12,
color: "blue",
description: "A beautiful ceramic vase",
}
end
let(:model) { described_class.new(attributes) }
context "with JSON serialization" do
it "serializes to JSON with custom methods" do
expected_json = {
name: "JSON Masterpiece: Vase",
color: "BLUE",
size: 15,
description: "JSON Description: A beautiful ceramic vase",
}.to_json
expect(model.to_json).to eq(expected_json)
end
it "deserializes from JSON with custom methods" do
json = {
name: "JSON Masterpiece: Vase",
color: "BLUE",
size: 15,
description: "JSON Description: A beautiful ceramic vase",
}.to_json
ceramic = described_class.from_json(json)
expect(ceramic.full_name).to eq(model.full_name)
expect(ceramic.size).to eq(model.size)
expect(ceramic.color).to eq(model.color)
expect(ceramic.description).to eq(model.description)
end
end
context "with XML serialization" do
it "serializes to XML with custom methods" do
expected_xml = <<~XML
XML Masterpiece: Vase
BLUE
XML Description: A beautiful ceramic vase
XML
expect(model.to_xml).to be_equivalent_to(expected_xml)
end
it "deserializes from XML with custom methods" do
xml = <<~XML
XML Masterpiece: Vase
BLUE
XML Description: A beautiful ceramic vase
XML
ceramic = described_class.from_xml(xml)
expect(ceramic.full_name).to eq(model.full_name)
expect(ceramic.size).to eq(model.size)
expect(ceramic.color).to eq(model.color)
expect(ceramic.description).to eq(model.description)
end
end
end