jsonperloopprivate-membersbless

Blessing a JSON into a perl class vs private properties


I have a Json structure such as:

{
  "field1" => "one",
  "field2" => "two",
  ...
}

I'm using the perl Json module, and I can bless the Json returned to me into a class, such as: my $result = bless($json->{output},'MyClass')

So far so good - now I can create methods within MyClass.pm to return the values of field1, field2, etc. So it seems that via bless, I have direct access to set the properties of an object. But the danger is that I can also do things later in the code like: $result->{field1} = "anythingIwant";

...which is not so good. I know I could set the property like _field1 to indicate privacy but that doesn't prevent me from doing $result->{_field1} = "anythingIwant";

So is there a best practice approach in perl to handle this situation? In other words, it's super convenient to be able to bless Json output into a class to deserialize, but it also seems dangerous. I'm looking for the best of both worlds where I can still use bless but also prevent any client code from doing the anythingIwant scenario described above. I've looked into Moose, InsideOut etc but I'm not really sure if either of those would fit the bill or just introduce more complexity.


Solution

  • Yes, the answer is to bless a closure.

    This can give you read-only access to the data (once you drop your original pointer) or both read and write access but only through your accessor method, never directly to the data:

    package MyClass;
    
    sub new {
        my $type = shift;
        my $class = ref $type || $type;
    
        my $self = shift;
    
        my $closure = sub {
                  $self->{$_[0]};
            };
    
         return bless $closure, $class;
    }
    
    package main;
    
    use strict;
    
    my $json_snippet = {
      "field1" => "one",
      "field2" => "two",
    };
    
    my $object = MyClass->new($json_snippet);
    
    print($object->("field2"), "\n");
    
    1;
    

    Here's an introduction to Objects with Private Variables