The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Perldoc::Data - Data structures as Perldoc streams

DESCRIPTION

The unlucky of us have to, at some point, try to shoe-horn their data objects into a document structure not designed for serialisation. Of course, you can do this with Perldoc.

To send a message, you point Perldoc::Data::Chill at a data structure. This structure currently should contain no circular references (unless appropriate marshalling methods are used); this limitation will be fixed by a later release.

The Perldoc::Data::Chill class acts as a Perldoc::Sender; so to actually write a document, you should connect it to a writer class, such as Perldoc::Writer::XML.

Here is an example of using this interface;

  my $chiller = Perldoc::Data::Chill->new(source => $structure);
  my $writer  = Perldoc::Writer::XML->new(output => "somefile.xml");
  $chiller->receiver($writer);
  $chiller->send_all;

Perldoc::Data::Chill provides per-class hooks for controlling the document marshalling; these are described on its man page.

Going the other way is a matter of connecting a stream of Perldoc events to Perldoc::Data::Thaw. This would normally come from a source such as a Perldoc::Parser::XML;

  my $reader = Perldoc::Reader->new(input => "source.xml");
  my $parser = Perldoc::Parser::XML->new(reader => $reader);
  my $warmer = Perldoc::Data::Thaw->new();
  $parser->receiver($warmer);
  $reader->send_all();

Perldoc::Data XML FORM

XML Data is nasty, but we're talking about a document structure here, so XML is a good way to describe it.

Scalars

All scalars are represented as a stream of characters. There is nothing at present to determine what data type they represent, other than context.

For example, the scalar "Foo", is represented as:

   Foo
Sets, Arrays and Hashes

Sets (well, actually only Set::Object containers) are represented identically to arrays.

The special tag <item> is used to denote an entry in an array or a hash. It may have one attribute; name, if it is an entry in a hash.

For instance, this hash:

  { "foo" => "bar",
    "baz" => "frop",
  }

Would be represented as:

  <item name="foo">bar</item>
  <item name="baz">frop</item>

If you are passing the document in to Perldoc::Data::Thaw, you can use, if it makes you feel better:

  <Hash>
    <item name="foo">bar</item>
    <item name="baz">frop</item>
  </Hash>

Arrays are a similar story; this array:

  [ "one", "two", [ "three part 1", "three part 2" ] ]

Would be represented as:

  <item>one</item>
  <item>two</item>
  <item>
    <item>three part 1</item>
    <item>three part 2</item>
  </item>

Or, if you wanted to be more explicit about where the collections are;

  <Array>
    <item>one</item>
    <item>two</item>
    <item>
      <Array>
        <item>three part 1</item>
        <item>three part 2</item>
      </Array>
    </item>
  </Array>

It is currently possible to have Perldoc::Data::Chill insert these extra tags, but still untested.

blessed objects

Objects (apart from Set::Object containers) are converted to an element, with attributes for properties and sub-elements for complex properties.

For instance, the following Perl object;

  bless({ Foo => "bar",
          Baz => "frop",
          Cheese => bless({ jeez => "louise" }, "Bert"),
        }, "Bob");

Would be represened in YAML as the simple;

  --- !perl/Bob
  Baz: frop
  Cheese: !perl/Bert
    jeez: louise
  Foo: bar

But this isn't a document about how easy it is to send data structures around using YAML. No, in our little XML language it looks like this:

  <Bob Baz="frop" Foo="bar">
    <Cheese>
      <Bert jeez="louise"/>
    </Cheese>
  </Bob>

This is actually converted to the following Perl structure on reassembly;

  Bob->new( Baz => "frop", Foo => "bar",
            Cheese => Bert->new( jeez => "louise" )
          );

This is a lot different to most serialisation systems in that it actually calls the constructor nicely. You can get it to call a different constructor by sub-classing Perldoc::Data::Thaw.

note: To get the above behaviour, you'd actually need to either turn on the unsafe mode mode of Perldoc::Data::Thaw, or pass in a classmap mapping element names to constructors;

  my $warmer_for_above_example = Perldoc::Data::Thaw->new
      ( classmap => { Bob => "Bob", Bert => "Bert" },
      );

Alternatively, you can tie the Perldoc::Data::Thaw object to a Perldoc::Scottish object (still in design stages) that is capable of performing appropriate decisions via various hooks in Perldoc::Data::Thaw that will no doubt receive testing sooner or later.

BUGS AND LIMITATIONS

See www.yaml.org for a way for sending data structures around that conforms to standards and doesn't suck kumara.

SEE ALSO

Perldoc::Data::Chill, Perldoc::Writer::XML, Perldoc::Data::Thaw, Perldoc::Parser::XML.