Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

perl6 class to-json exclude properties

Tags:

json

class

raku

I have been driving myself crazy trying to find a module that I can use with nested objects specifically classes. There are a few modules that are pretty close however I do not want to set the properties to null to skip the values I do not want.

It would be great if I could write a TO_JSON method or so to that returns a structure that will be marshaled by a module. Or, just use "json-skip" on attributes we don't want included in the final JSON document.

Something like:

class Something {
   has Str $.foo;
   has Str $.bar is json-skip;

}

or

class Something { 
   has Str $.foo;
   has Str $.bar;

   method TO_JSON {
      return {
          foo => $.foo
      }
   }
}

JSON::Tiny, JSON::Fast, JSON::Marshal, etc... all work great with individual structures and some even with nested instances however excluding properties is eluding me at the moment.

At the end I would like to do something like:

my $json-document = to-json(@nestedInstances);
like image 951
Daniel Maldonado Avatar asked Nov 01 '18 22:11

Daniel Maldonado


2 Answers

The sub to-json from JSON::Tiny is multi. So you can redefine the behavior for you class.

multi sub to-json ( Something $_ ) {
    to-json 'foo' => .foo
}

Thus following example probably works as you want.

use JSON::Tiny;

class Something { 
   has Str $.foo;
   has Str $.bar;

   method TO_JSON {
      return {
          foo => $.foo
      }
   }
}

multi sub to-json ( $_ where *.can('TO_JSON') ) {
    to-json .TO_JSON
}

my Something $sth .=  new: :foo<interest>, :bar<no_interest>;

say to-json [$sth,2, :$sth];

Output:

[ { "foo" : "interest" }, 2, { "sth" : { "foo" : "interest" } } ]
like image 57
wamba Avatar answered Nov 13 '22 05:11

wamba


The above answer is the accepted answer and I have made it an issue in the JSON::Tiny github repo. The code below is just to clarify what is happening for those of us that are new to perl6:

use JSON::Tiny;
# The JSON::Tiny module has a bunch of multi to-json subs.
# Here we are creating/adding one that takes an instance that can do "TO_JSON", i.e. has a TO_JSON method
multi to-json ( $_ where *.can('TO_JSON') ) {
   # Execute the method TO_JSON on the passed instance and use one of
   #  the other to-json subs in the JSON::Tiny module that supports the
   #  returned structure
   to-json $_.TO_JSON
}

class Something { 
   has Str $.foo;
   has Str $.bar;

   method TO_JSON {
      return {
          foo => $.foo
      }
   }
}

my Something $sth = Something.new( foo => 'Interested', bar => 'Not interested' );

# The lexically scoped to-json sub above is used because it takes an argument that implements the TO_JSON method
say to-json $sth;

output:

{ "foo" : "Interested" }
like image 2
Daniel Maldonado Avatar answered Nov 13 '22 05:11

Daniel Maldonado