http://www.perlmonks.org?node_id=968331

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I am using YAML::XS to load yaml generated in Java. Is there a way to keep YAML::XS from blessing objects? If not, I wanted to overload stringification for java.util.UUID objects but perl won't let me declare the package.
use YAML::XS; my $ref = YAML::XS::Load(join('',<DATA>)); print "$ref->{fooUuid}\n"; print ref $ref->{fooUuid}, "\n"; 1; __DATA__ --- fooUuid: !java.util.UUID 39809f4e-93b9-11e1-89b4-db41381ff4b7
Suggestions on how to get YAML::XS to not bless my refs, how to declare a package with name 'java.util.UUID', or other suggestions on fixing stringification are appreciated.

Replies are listed 'Best First'.
Re: Dealing with blessed scalars when using YAML::XS::Load
by Khen1950fx (Canon) on May 02, 2012 at 05:28 UTC
    Maybe using YAML::Dumper would help?
    #!/usr/bin/perl use strict; use warnings; use YAML::XS; use YAML::Dumper; my $ref = YAML::XS::Load(join('',<DATA>)); my $dumper = YAML::Dumper->new; print $dumper->dump($$ref{'fooUuid'}); print $dumper->dump(ref $$ref{'fooUuid'}); __DATA__ --- fooUuid: !java.util.UUID 39809f4e-93b9-11e1-89b4-db41381ff4b7
Re: Dealing with blessed scalars when using YAML::XS::Load
by tye (Sage) on May 01, 2012 at 23:10 UTC

    My advice would be to stop using YAML and switch to JSON ("overcomplicated" so often turns out to be a problem, as this example illustrates). ;)

    Is there a way to keep YAML::XS from blessing objects?

    http://cpansearch.perl.org/src/INGY/YAML-LibYAML-0.38/LibYAML/perl_libyaml.c makes it clear that the answer is "no":

    /* Deal with possibly blessing the hash if the YAML tag has a clas +s */ if (tag && strEQ(tag, TAG_PERL_PREFIX "hash")) tag = NULL; if (tag) { char *class; char *prefix = TAG_PERL_PREFIX "hash:"; if (*tag == '!') { prefix = "!"; } else if (strlen(tag) <= strlen(prefix) || ! strnEQ(tag, prefix, strlen(prefix)) ) croak( loader_error_msg(loader, form("bad tag found for hash: '%s +'", tag)) ); class = tag + strlen(prefix); sv_bless(hash_ref, gv_stashpv(class, TRUE)); }
    how to declare a package with name 'java.util.UUID'

    Well, I can imagine ways to do that. But you don't even bother to show the output of your little snippet and I'm not going to bother to download YAML::XS (which I have no plans to ever use) so I don't have a good idea what kind of "hash" libyaml is supposed to make out of the little example blob of text you included. So my demonstration may not be one that will actually work on your example:

    BEGIN { { package YAML::Sucks::JavaUtilUUID::_alias; @ISA = 'YAML::Sucks::JavaUtilUUID'; } $main::{'java.util.UUID::'} = $YAML::Sucks::JavaUtilUUID::{'_alias +::'}; } { package YAML::Sucks::JavaUtilUUID; use overload '""' => \&asString; sub asString { my( $self ) = @_; return join ' ', values %$self; } } my $fromYaml = bless { whatever => 'some UUID?' }, 'java.util.notUUID' +; print "($fromYaml)\n"; $fromYaml = bless { whatever => 'some UUID?' }, 'java.util.UUID'; print "($fromYaml)\n"; __END__ (java.util.notUUID=HASH(0x367c44)) (some UUID?)

    (Speaking of "overcomplicated", eh?) Or you could just use unbless instead.

    Like I mentioned, I don't know what key name(s) libyaml is creating for that example. But you should be able to use $ref->{foo­Uuid}{$whatever} in place of $ref->{foo­Uuid}, regardless of the bless()ing (to get at the string that I presume that you want).

    - tye        

      tye, Thank you for the solution. I'm sorry I did not include the output. It's a scalar ref. Output:
      java.util.UUID=SCALAR(0x100800e60) java.util.UUID
      I looked at unbless but we are changing YAML handling in a framework used by other people, so the solution needs to result in scalars or objects that can be treated like strings. I appreciate the suggestion though. Can you explain why you put the _alias step in? What is the advantage? I found this equally effective:
      BEGIN { { package YAML::Sucks::JavaUtilUUID; } $main::{'java.util.UUID::'} = $YAML::Sucks::{'JavaUtilUUID::'}; }
      Again, thanks.

        Aliasing a package like that is not expected. There may be things that break in the face of it. So I reduced the number of things that have to deal with that aliased package to a single thing, @ISA. Then one doesn't have to worry about ambiguity in the code context or name of a method or ref-counting issues or some other problem that might result from the hackish aliasing.

        - tye        

      Actually, the JSON package will also created blessed scalars to represent booleans.

      It creates JSON::XS::Boolean scalars.