bidy
bidy

Reputation: 13

How can I tell if a JSON string has no elements, in Perl?

I'm trying to compare a string to another.

If it's a JSON structure which contains things, I want to print "contains things". If it's a JSON structure which doesn't contain thing, I print "empty" If it something which is not between curly brackets "{}", i print that there's an error.

Here's what I've done :

if($content =~ m/{.+}/){
    print "Contains things \n";
} elsif($content eq "{}"){
    $job_status{$url}="";
    print "empty \n";
} else {
    print "Error \n";
}

When I pass "{}" to the variable $content, he does not enter the "elsif", but go to the "else", and throw an error.

I've tried to put "==" instead the "eq" in the if, even though I know it's for numbers. When so, he enters the "elsif", and print "empty", like he should do with the "eq", and throws :

Argument "{}" isn't numeric in numeric eq (==)". 

I could use the JSON library, but I prefer not to.

Upvotes: 0

Views: 168

Answers (4)

choroba
choroba

Reputation: 242423

I can replicate the behaviour if I add a newline after the {}:

#!/usr/bin/perl
use strict;
use warnings;

my $content = "{}\n";

if($content =~ m/{.+}/s){
    print "Contains things \n";
} elsif($content eq "{}"){
    print "empty \n";
} else {
    print "Error \n";
}

It returns "Error", if I replace eq with ==, it returns empty, because both "{}" and "{}\n" are numerically 0. A warning is thrown as you mentioned.

You might try to chomp the $content before processing it.

Upvotes: 1

toolic
toolic

Reputation: 62236

It works for me. Does $content have a newline character? Try chomp $content;.

use warnings;
use strict;

my $content = '{}';
if($content =~ m/{.+}/s){
    print "Contains things \n";
} elsif($content eq "{}"){
    print "empty \n";
} else {
    print "Error \n";
}

__END__

empty 

Upvotes: 1

brian d foy
brian d foy

Reputation: 132914

Heh, I don't like my answer from 8 years ago. Today I'd prefer to just check the JSON:

use v5.36;
use experimental qw(builtin);
use builtin qw(reftype); # or get it from Scalar::Util

use JSON;

my @inputs = (
    '{', '}', 'abc',
    '{}', '{"a":"b"}',
    );

foreach my $input ( @inputs ) {
    my $json = eval { decode_json( $input ) };

    my $empty =
        defined( $json ) &&
        ( reftype $json eq reftype {} and 0 == keys $json->%* );

    say "INPUT: $input --> ", $empty ? 'Empty' : 'Not empty (or not JSON)';
    }

And, there's jq if you are outside of a program:

$ jq '. == {}' <<< "{}"
true

$ jq '. != {}' <<< "{}"
false

A top-level JSON thingy can be an object ({...}) or an array ([...]), but you're only checking for one of those. If you merely want to see if it's empty, I'd check the length of the string:

chomp $possible_json;
if( $length $possible_json >= 3 ) { ... }

You might also consider Randal Schwartz's regex for JSON parsing. It doesn't handle everything, but it's often enough for simple things.

Upvotes: 1

ElectricWeasel
ElectricWeasel

Reputation: 107

I'd probably end up breaking it up:

unless ($content) {print "Error\n"};
$content =~ /{(.*)}/
my $resp = $1;
if ($resp) {
 print "Contains Things ($resp)\n";
} else {
 print "Empty\n";
}

Upvotes: 0

Related Questions