skip to Main Content

I am getting a json response from an API endpoint that is something like this:

    {
            "items": [
                {
                    "key": "",
                    "groupReference": "mastercard-XXXXXXXXXXXXXXX",
                    "type": "firstPresentment-dms",
                    "created": "2023-01-27T10:07:56.038Z",
                    "entry": 1,
                    "isCorrection": false,
                    "reportingFor": "0000",
                    "network": "mastercard",
                    "fundsTransferDate": "2023-01-27",
                    "fundsTransferBookDate": "2023-01-27",
                    
                }
            ]
}

I have used decode_json() to decode this. The problem is since the isCorrection is a pure perl boolean value, the decoding doesn’t work properly and I get this

Reference of JSON::PP::Boolean$VAR1 = bless( do{(my $o = 0)}, 'JSON::PP::Boolean' );

Any idea how to fix this issue?

2

Answers


  1. the decoding doesn’t work properly

    Oh, but it does. The documentation for the mapping from JSON to Perl includes this:

    true, false

    These JSON atoms become JSON::PP::true and JSON::PP::false, respectively. They are overloaded to act almost exactly like the numbers 1 and 0. You can check whether a scalar is a JSON boolean by using the JSON::PP::is_bool function.

    So if you treat the value you get as a boolean, everything will Just Work:

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    use feature 'say';
    
    use JSON::PP;
    
    my $response = '{
      "items": [
        {
          "key": "",
          "groupReference": "mastercard-XXXXXXXXXXXXXXX",
          "type": "firstPresentment-dms",
          "created": "2023-01-27T10:07:56.038Z",
          "entry": 1,
          "isCorrection": false,
          "reportingFor": "0000",
          "network": "mastercard",
          "fundsTransferDate": "2023-01-27",
          "fundsTransferBookDate": "2023-01-27"
        }
      ]
    }';
    
    
    my $data = decode_json($response);
    
    if ($data->{items}[0]{isCorrection}) {
      say "Value is true";
    } else {
      say "Value is false";
    }
    

    Things will only go wrong if you break encapsulation and start expecting specific values there. But you can probably fix that using OO version of the interface and the boolean_values() or core_bools() methods.

    Login or Signup to reply.
  2. What you see is how it is supposed to work. This way, if you re-encode that as JSON, you get the right JSON boolean values and not 0 or 1.

    Dave Cross’s answer shows that you shouldn’t have to think about it. But, if there’s some reason you need to convert it to plain 1 or 0, there are some Perl idioms:

    use v5.10;
    
    use JSON;
    
    foreach my $value ( qw(true false) ) {
        say "---- $value ----";
        my $hash = decode_json( qq({ "items": $value }) );
        say "conditional: " , $hash->{items} ? 1 : 0;
        say "plus: ",  0 + $hash->{items};
        say "double bang: ",  !! $hash->{items};
        say "plain: ",  $hash->{items};
        }
    

    Here’s the output:

    ---- true ----
    conditional: 1
    plus: 1
    double bang: 1
    plain: 1
    ---- false ----
    conditional: 0
    plus: 0
    double bang:
    plain: 0
    

    Note that the !! in the false case does not give back zero. Instead, it’s the empty string. I include that because you’ll see that idiom to double negate a value, although that’s more about turning a non-zero length string into 1 or the empty string.

    The conditional version is probably more appropriate if you need to select one of two special values (perhaps for a database column):

    my $insert_this_value = $hash->{items} ? $TRUE_VALUE : $FALSE_VALUE;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search