【问题标题】:How do I serialize Moose objects to XML?如何将 Moose 对象序列化为 XML?
【发布时间】:2017-07-16 19:26:19
【问题描述】:

我有一堆遗留模块想要转换为基于 Moose 的。这些模块目前具有“toXML”方法,这些方法是使用 XML::LibXML 手动编码的。

是否有将 Moose 对象序列化为 XML 的模块或技术?

我看过 MooseX::Storage,但它处理 JSON、YAML 和存储,而不是 XML。谷歌搜索 Moose 和 XML 会产生大量对 XML::Rabbit 的引用,这似乎很适合将 XML 解析为 Moose 类,但对于获取 Moose 对象并将它们序列化为 XML 的情况并不多。

http://grokbase.com/t/perl/moose/11akp809sr/java-annotation-net-attributes-in-moose 的 6 年前的帖子非常接近我想要做的事情,但似乎没有任何后续行动。

【问题讨论】:

  • MooseX::Storage 通过使用MooseX::Storage::Format::JSON 角色来实现。据我所知,这是我们那里唯一的MooseX::Storage::Format 序列化角色。也许自己写? Format::JSON 的代码只有几十行(使用模块)。我不知道你到底需要序列化什么,但也许XML::Dumper 可以提供帮助。它声称能够处理对象。
  • @zdim, Re "据我所知,这是我们那里唯一的 MooseX::Storage::Format 序列化角色", MooseX::Storage::Format: :JSON、...::YAML 和 ...::Storable 都带有 MooseX::Storage。
  • @Blaise Pascal,所以写 MooseX::Storage::Format::XML。
  • @ikegami 对。我的意思是我没有看到MooseX::Storage::Format下的任何其他模块
  • 在使用 MooseX::Storage 时必须考虑的事情是,例如,将对象保存在键/值存储中(例如,ecom 应用程序中的产品对象),并且您有很多对于不同产品类型的不同子类,您必须在应用程序的某个位置加载所有这些子类,因为 MooseX::Storage 无法为您做到这一点。您当然可以教它这样做,但是加载所有这些类更容易,例如在您的主应用程序类中。

标签: xml perl serialization moose


【解决方案1】:

MooseX::Storage 使用MooseX::Storage::Format::JSONrole 序列化JSON 中的数据,这是如何插入其他格式的一个很好的例子。我看不到XML 序列化的任何角色,但是很容易编写自己的角色,并且模块为它提供了一个钩子。

这个最小的例子展示了如何编写一个role并在一个类中consume(使用)它。角色是一个类包,它永远不会自己实例化,而是被其他类吸收。它旨在提供可以轻松“插入”并由多个类使用的功能。最后展示了如何将新角色挂接到MooseX::Storage,然后在您的班级中使用它。

它使用XML::Dumper 进行序列化本身,主要用作自定义代码的占位符(如果需要)。

Point.pm

package Point;    

use Moose;

use overload  q("") => sub { 
    my $self = shift; 
    return '(' . $self->x . ', ' . $self->y . ')' 
};  

has 'x' => (is => 'rw', isa => 'Int', required => 1, default => 0); 
has 'y' => (is => 'rw', isa => 'Int', required => 1, default => 0); 

with 'SerializeXML';

sub BUILD { print "Created a Point $_[0]\n" }

__PACKAGE__->meta->make_immutable;    
1;

这里唯一的具体声明是with 'SerializeXML';这一行

SerializeXML.pm

package SerializeXML;

use Moose::Role;    
use XML::Dumper;

sub to_xml {
    my ($self) = shift;
    return XML::Dumper->new->pl2xml($self);  # or use custom code
}

sub from_xml {
    my ($self, $xml) = @_; 
    return XML::Dumper->new->xml2pl($xml);
}
    
no Moose::Role;
1;

XML 构造对象应该通过new 和/或作为类方法来完成。

主要

use warnings;
use strict;

use Point;

my $pt = Point->new(x => 10, y => 12);

my $obj_xml = $pt->to_xml;
print "$obj_xml\n";

my $obj = $pt->from_xml($obj_xml);
print "Object via role: $obj\n";

打印出来

Created a Point (10, 12)
<perldata>
 <hashref blessed_package="Point" memory_address="0x1691438">
  <item key="x">10</item>
  <item key="y">12</item>
 </hashref>
</perldata>
Object via role: (10, 12)

可以添加用于写入文件和从文件加载的方法。但是现在你有一个现成的角色,可以挂接到MooseX::Storage,如下所示。

我不知道也没有测试过XML::DumperMoose 的工作情况。请进行测试,如果它不能满足您的需要,请使用您自己的代码来满足您的需求。


如果需要,剩下的步骤是将其集成到 MooseX::Storage 中。

在上面的代码中有两个必要的小改动。使用Point中的角色作为

use MooseX::Storage;

with Storage(format => '=SerializeXML', io => 'File');

并将 to_xmlfrom_xml 重命名为 freezethaw(或添加这些,使用相同的代码)。

然后您可以在main 中使用storeload 来写入$file 并从中加载

$pt->store($file);
my $pt_new = Point->load($file);

语法=PackageName 用于MooseX::Storage::Format:: 以外的命名空间前缀

有关角色,请参阅 Moose::Manual::RolesMoose::Cookbook::Roles:: 命名空间(示例)。

【讨论】:

  • 这是一个非常好的指南。如果特别需要 XML,我们可以假设 OP 知道他们对 XML 的处理方式,因此 XML::Dumper 可能是 XML::Compile 的替代方案。如果他们编写一个实际的 XML 模式并将其与数据一起输入 XML::Compile,他们甚至可以轻松地接受来自外部源的数据,以直接通过给出模式来创建对象。
  • @simbabque 谢谢。它本来是基本的。我不想碰XML 处理,因为那是另一个问题。这是你提供的一个好主意。也许 OP 应该将XML 作为一个单独的问题询问,并说明他们在做什么以及为什么选择这种格式。
  • 我正在处理遗留代码/遗留数据,所以我没有选择 XML 格式,只是从一两年前做出决定的人那里继承了它。不幸的是,这意味着不能使用XML::Dumper,因为它没有转储正确的格式。现有的MooseX::Storage::Format 模块基本上封装了像XML::Dumper 这样的现有转储程序,但不对格式进行任何控制。这不是我需要的。
  • @BlaisePascal 等一下……在上面的代码中,您可以插入任何您想要的XML 处理。 (例如,您/他们现有的库,如果它们有效的话。)它为您提供了切换到 Moose 的框架,这就是您在我的理解中提出的问题。这就是我没有接触XML 的原因——我使用XML::Dumper 作为特定XML 处理细节的占位符。我误解了这个问题吗?
  • @BlaisePascal XML 没有“现有的MooseX::Storage::Format 模块”(据我所知)。但是整个MooseX::Storage 是这样编写的,因此很容易为任何所需格式插入“角色”,这就是我在上面要展示的内容。然后你为你的特定目的编写/使用合适的代码。同样,我遵循“想要转换为基于 Moose 的”——您使用现有代码添加角色(如果有效)。
【解决方案2】:

所以MooseX::Storage 没有 XML 存储格式的原因之一是,正如您所发现的,大多数人都有他们需要写入的传统 XML 格式。 XML 和 Perl 实际上有非常不同的方式来表示数据,并且找出正确的方式在两者之间进行转换实际上并不是您可以自动完成的事情。

您不会找到“现成”选项本身。正如 simbabque 在评论中提到的,如果您拥有或可以轻松地为您的数据构建架构,那么 XML::Compile 或 'XML::Pastormight work for you (XML::Compileis better maintained). If you're willing to do some grunt workXML::Toolkitis designed to translate an example document into a series of Moose classes that it can then later re-serialize. However I haven't touchedXML::Toolkit`在 很长 的时间内,让 YMMV 了解它需要运行的内容。

我认为最终您会发现最简单的解决方案是您已经拥有的手动构建的toXML 方法。 Moose 并没有阻止你这样做,实际上它为你提供了一堆工具来弄清楚如何使它更易于维护。看看 MooseX::Storage 本身是如何实现的,就能看到一条好的前进道路。

【讨论】:

    猜你喜欢
    • 2018-09-05
    • 2011-12-03
    • 2019-03-04
    • 2018-10-11
    • 2017-08-20
    • 2011-01-07
    • 2011-05-06
    相关资源
    最近更新 更多