SOAP::Serializer(3)

okay so bestie, welcome to the manual page for SOAP::Serializer(3) โ€” yes, the User Contributed Perl Documentation one โ€” and it's literally about how the toolkit turns data into XML. grab a lil snack ๐Ÿ“, we're going in.

๐ŸŒธ NAME ๐ŸŒธ

SOAP::Serializer โ€” the means by which the toolkit manages the expression of data as XML. periodt. ๐Ÿ’…

โœจ DESCRIPTION โœจ

The SOAP::Serializer class is the means by which the toolkit manages the expression of data as XML. The object that a SOAP::Lite instance uses by default is generally enough for the task, with no need for the application to create its own. The main purpose of this class is to provide a place for applications to extend the serializer by defining additional methods for handling new datatypes.

๐Ÿ’– METHODS ๐Ÿ’–

๐Ÿ’ซ new(optional key/value pairs)

$serialize = SOAP::Serializer->new( );

This is the constructor method for the class. In addition to creating a basic object and initializing it with default values, the constructor can also take names and values for most of the accessor methods that the class supports. constructor slay ๐Ÿซถ

๐Ÿ”ฅ envelope(method, data arguments)

$serialize->envelope(fault => $fault_obj);

Provides the core purpose for the SOAP::Serializer class. It creates the full SOAP envelope based on the input passed in to it.

The data arguments passed in the list of parameters to the method are divided into two sublists: any parameters that are SOAP::Header objects or derivatives of go into one list, while the remainder go into the other. The nonheader objects are used as the content for the message body, with the body itself being largely dependent on the value of the first argument in the list. This argument is expected to be a string and should be one of the following โ€” and yes, the manpage drops a context method right here before listing the four actual envelope values, so we're rolling with that exact order, bestie:

๐Ÿงš context

$serialize->context->packager();

This provides access to the calling context of SOAP::Serializer. In a client side context this often means a reference to an instance of SOAP::Lite. In a server side context this means a reference to a SOAP::Server instance.

For that first envelope argument, the allowed values are:

  • method โ€” the envelope is being created to encapsulate a RPC-style method call.
  • response โ€” the message being created is that of a response stemming from a RPC-style method call.
  • fault โ€” for this specifier, the envelope being created is to transmit a fault.
  • freeform โ€” this identifier is used as a general-case encoding style for messages that don't fit into any of the previous cases. The arguments are encoded into the envelope's Body tag without any sort of context sensitivity.
bestie, any value other than these four results in an error. no cap. ๐Ÿ’€

๐ŸŒˆ envprefix(optional value)

$serialize->envprefix('env');

Gets or sets the prefix that labels the SOAP envelope namespace. This defaults to SOAP-ENV.

๐Ÿฆ‹ encprefix(optional value)

$serialize->envprefix('enc');

Gets or sets the prefix that labels the SOAP encoding namespace. Defaults to SOAP-ENC.

okay copy that snippet exactly as shown, bestie โ€” the page literally has envprefix there, and we are not fixing it. ๐Ÿ’…

โญ soapversion(optional value)

$serialize->soapversion('1.2');

If no parameter is given, returns the current version of SOAP that is being used as the basis for serializing messages. If a parameter is given, attempts to set that as the version of SOAP being used. The value should be either 1.1 or 1.2.

When the SOAP version is being set, the package selects new URNs for envelope and encoding spaces and also calls the xmlschema method to set the appropriate schema definition.

๐ŸŽ€ xmlschema(optional value)

$serialize->xmlschema($xml_schema_1999);

Gets or sets the URN for the schema being used to express the structure of the XML generated by the serializer. If setting the value, the input must be the full URN for the new schema and is checked against the list of known SOAP schemas.

๐Ÿ‘‘ register_ns

The register_ns subroutine allows users to register a global namespace with the SOAP Envelope. The first parameter is the namespace, the second parameter to this subroutine is an optional prefix. If a prefix is not provided, one will be generated automatically for you. All namespaces registered with the serializer get declared in the <soap:Envelope /> element.

๐Ÿ“ find_prefix

The find_prefix subroutine takes a namespace as a parameter and returns the assigned prefix to that namespace. This eliminates the need to declare and redeclare namespaces within an envelope. This subroutine is especially helpful in determining the proper prefix when assigning a type to a SOAP::Data element.

A good example of how this might be used is as follows:

SOAP::Data->name("foo" => $inputParams{'foo'})
   ->type($client->serializer->find_prefix('urn:Foo').':Foo');

๐Ÿฆ‹ CUSTOM DATA TYPES ๐Ÿฆ‹

When serializing an object, or blessed hash reference, into XML, SOAP::Serializer first checks to see if a subroutine has been defined for the corresponding class name. For example, in the code below, SOAP::Serializer will check to see if a subroutine called as_MyModule__MyPackage has been defined. If so, then it will pass $foo to that subroutine along with other data known about the SOAP::Data element being encoded.

$foo = MyModule::MyPackage->new;
my $client = SOAP::Lite
   ->uri($NS)
   ->proxy($HOST);
$som = $client->someMethod(SOAP::Data->name("foo" => $foo));

๐Ÿ’œ as_TypeName SUBROUTINE REQUIREMENTS ๐Ÿ’œ

๐ŸŒŸ Naming Convention

The subroutine should always be prepended with as_ followed by the type's name. The type's name must have all colons (':') substituted with an underscore ('_').

๐ŸŒธ Input

The input to as_TypeName will have at least one parameter, and at most four parameters. The first parameter will always be the value or the object to be encoded. The following three parameters depend upon the context of the value/object being encoded.

If the value/object being encoded was part of a SOAP::Data object (as in the above example), then the second, third and fourth parameter will be the SOAP::Data element's name, type, and attribute set respectively. If on the other hand, the value/object being encoded is not part of a SOAP::Data object, as in the code below:

$foo = MyModule::MyPackage->new;
my $client = SOAP::Lite
   ->uri($NS)
   ->proxy($HOST);
$som = $client->someMethod($foo);

Then the second and third parameters will be the class name of the value/object being encoded (e.g. MyModule::MyPackage in the example above), and the fourth parameter will be an empty hash.

๐ŸŽ€ Output

The encoding subroutine must return an array containing three elements: 1) the name of the XML element, 2) a hash containing the attributes to be placed into the element, and 3) the value of the element.

๐Ÿ”ฎ AUTOTYPING ๐Ÿ”ฎ

okay so when an element's type hasn't been declared explicitly, SOAP::Lite has to "guess" at the object's type. that's literally because the only form of introspection Perl gives us โ€” through the ref subroutine โ€” doesn't provide enough info to SOAP::Serializer to let SOAP::Lite figure out the exact type of an element being serialized. no cap ๐Ÿ˜ญ

to work around this limitation, the SOAP::Serializer::typelookup hash was created. this hash is populated with all the data types that the current SOAP::Serializer can auto detect. users and developers are free to modify the contents of this hash, which lets them register new data types with the system. slay ๐Ÿ’…

when SOAP::Serializer is asked to encode an object into XML, it goes through these steps. first, SOAP::Serializer checks to see if a type has been explicitly stated for the current object. if a type has been provided, SOAP::Serializer checks to see if an as_TypeName subroutine has been defined for that type. if such a subroutine exists, then SOAP::Serializer passes the object to it to be encoded. if the subroutine does not exist, or the type has not been provided, then SOAP::Serializer must attempt to "guess" the type of the object being serialized. ๐Ÿงš

to do so, SOAP::Serializer runs in sequence a set of tests stored in the SOAP::Serializer::typelookup hash. SOAP::Serializer continues to run each test until one of the tests returns true, indicating that the type of the object has been detected. when the type of the object has been detected, then SOAP::Serializer passes the object to the encoding subroutine that corresponds with the test that was passed. if all the tests fail, and the type was not determined, then SOAP::Serializer will as a last resort encode the object based on one of the four basic data types known to Perl: REF, SCALAR, ARRAY and HASH. periodt ๐Ÿ”ฅ

the following table contains the set of data types detectable by SOAP::Lite by default and the order in which their corresponding test subroutine will be run, according to their precedence value.

Table 1 - Autotyping Precedence

  • base64 โ€” precedence value 10
  • int โ€” precedence value 20
  • long โ€” precedence value 25
  • float โ€” precedence value 30
  • gMonth โ€” precedence value 35
  • gDay โ€” precedence value 40
  • gYear โ€” precedence value 45
  • gMonthDay โ€” precedence value 50
  • gYearMonth โ€” precedence value 55
  • date โ€” precedence value 60
  • time โ€” precedence value 70
  • dateTime โ€” precedence value 75
  • duration โ€” precedence value 80
  • boolean โ€” precedence value 90
  • anyURI โ€” precedence value 95
  • string โ€” precedence value 100

๐Ÿ’– REGISTERING A NEW DATA TYPE ๐Ÿ’–

to register a new data type that can be automatically detected by SOAP::Lite and then serialized into XML, the developer must provide the following four things:

  • the name of the new data type ๐ŸŽ€
  • a subroutine that is capable of detecting whether a value passed to it is of the corresponding data type
  • a number representing the test subroutine's precedence relative to all the other types' test subroutines. see Table 1 - Autotyping Precedence ๐Ÿ‘€
  • a subroutine that is capable of providing SOAP::Serializer with the information necessary to serialize an object of the corresponding data type into XML

๐ŸŽ€ EXAMPLE 1 ๐ŸŽ€

if, for example, you wish to create a new datatype called uriReference for which you would like Perl values to be automatically detected and serialized into, then you follow these steps. bestie, it's giving tutorial era โœจ

Step 1: Write a Test Subroutine

the test subroutine will have passed to it by SOAP::Serializer a value to be tested. the test subroutine must return 1 if the value passed to it is of the corresponding type, or else it must return 0.

sub SOAP::Serializer::uriReferenceTest {
  my ($value) = @_;
  return 1 if ($value =~ m!^http://!);
  return 0;
}

Step 2: Write an Encoding Subroutine

the encoding subroutine provides SOAP::Serializer with the data necessary to encode the value passed to it into XML. the encoding subroutine's name should be of the following format: as_<Type Name>.

the encoding subroutine will have passed to it by SOAP::Serializer four parameters: the value to be encoded, the name of the element being encoded, the assumed type of the element being encoded, and a reference to a hash containing the attributes of the element being encoded. the encoding subroutine must return an array representing the encoded datatype. SOAP::Serializer will use the contents of this array to generate the corresponding XML of the value being encoded, or serialized. this array contains the following 3 elements: the name of the XML element, a hash containing the attributes to be placed into the element, and the value of the element. ๐Ÿ’œ

sub SOAP::Serializer::as_uriReference {
  my $self = shift;
  my($value, $name, $type, $attr) = @_;
  return [$name, {'xsi:type' => 'xsd:uriReference', %$attr}, $value];
}

Step 3: Register the New Data Type

to register the new data type, simply add the type to the SOAP::Serializer::typelookup hash using the type name as the key, and an array containing the precedence value, the test subroutine, and the encoding subroutine.

$s->typelookup->{uriReference}
    = [11, \&uriReferenceTest, 'as_uriReference'];

tip: as a short hand, you could just as easily use an anonymous test subroutine when registering the new datatype in place of the urlReferenceTest subroutine above. for example:

$s->typelookup->{uriReference}
    = [11, sub { $_[0] =~ m!^http://! }, 'as_uriReference'];

once complete, SOAP::Serializer will be able to serialize the following SOAP::Data object into XML:

$elem = SOAP::Data->name("someUri" => 'http://yahoo.com')->type('uriReference');

SOAP::Serializer will also be able to automatically determine and serialize the following untyped SOAP::Data object into XML:

$elem = SOAP::Data->name("someUri" => 'http://yahoo.com');

๐ŸŒˆ ACKNOWLEDGEMENTS ๐ŸŒˆ

special thanks to O'Reilly publishing which has graciously allowed SOAP::Lite to republish and redistribute large excerpts from Programming Web Services with Perl, mainly the SOAP::Lite reference found in Appendix B. iconic behavior honestly ๐Ÿซถ

Copyright (C) 2000-2004 Paul Kulchenko. All rights reserved.

this library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. ๐Ÿ’–

๐Ÿซถ AUTHORS ๐Ÿซถ

  • Paul Kulchenko (paulclinger@yahoo.com)
  • Randy J. Ray (rjray@blackperl.com)
  • Byrne Reese (byrne@majordojo.com)

and that's the whole page, bestie โ€” source/version and date tea: perl v5.42.0, 2024-03-04, and this absolute icon is SOAP::Serializer(3). mwah ๐Ÿ’‹๐ŸŽ€

๐Ÿ“ฆ where this page comes from