Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

String to Integer, for json file

by halecommarachel (Sexton)
on Dec 12, 2013 at 04:23 UTC ( [id://1066762]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks, I have a data structure that I'm converting to a json string, which I then write to a file. The json file is used for a database. To convert the strings containing only digits to numbers, I add zero and then store in the structure. For some reason, when I look at the json file, some strings that were supposed to be converted to integers are still strings. Is there any way to guarantee a string is converted to a integer? Thanks!

So a data dump looks good: 'cl_ip' => 209889, But there's a string in the json file for this key: "cl_ip":"209889"

Replies are listed 'Best First'.
Re: String to Integer, for json file
by davido (Cardinal) on Dec 12, 2013 at 05:39 UTC

    JSON is more strongly typed than Perl. Perl (the language) is designed to not really make a strong distinction between an integer and a string. But internally there is a distinction. The "SV" entity that comprises a Perl scalar variable may have an "IV" (integer value) stored in it, or a "PV" (pointer to a string), or both (as well as a few other things). Perl mostly silently vivifies PV's and IV's within scalars as needed. So if you start with $var = 100;, that scalar variable holds just an IV. Now if you say print "$var\n";, $var goes through a stringification process that results in a PV being created within the scalar too. This is all taking place hidden behind the black box of Perl's internals, and in most circumstances this implementation detail is not relevant or even noticed.

    However, JSON is typed, and JSON encoders have to decide whether a scalar contains an integer or a string. Most of the time the way they decide is by looking inside the variable to see if there is a PV. Remember, scalars may contain both. But the existence of an IV is overruled by the existence of a PV.

    So you have to be very careful that this variable you're encoding has never been treated as a string. Or that a new variable is used: my $new_var = 0 + $var;.


    Dave

      Thank you davido for the explanation, it has truly enlightened me.
        A string can become a number again :) Its the flags that reveal the true nature (last touch)
        use JSON qw/ to_json from_json /;
        use Devel::Peek qw/ Dump /;
        my $q = 3;
        print "$q\n";
        Dump( $q );
        $q++;
        Dump( $q );
        print to_json( { a => 3, qw/ b 3 q/, $q } );
        __END__
        3
        SV = PVIV(0x9a3778) at 0x99b524
          REFCNT = 1
          FLAGS = (PADMY,IOK,POK,pIOK,pPOK)
          IV = 3
          PV = 0xad23fc "3"\0
          CUR = 1
          LEN = 12
        SV = PVIV(0x9a3778) at 0x99b524
          REFCNT = 1
          FLAGS = (PADMY,IOK,pIOK)
          IV = 4
          PV = 0xad23fc "3"\0
          CUR = 1
          LEN = 12
        {"a":3,"q":4,"b":"3"}
        http://search.cpan.org/dist/illguts/index.html

      Thank you, davido. This is a very useful explanation. I tried creating a new variable and then storing it in the hash, but I'm still seeing the string in the json file.

Re: String to Integer, for json file
by karlgoethebier (Abbot) on Dec 12, 2013 at 08:51 UTC

    Looks like JSON::XS does the job:

    use JSON::XS; use Data::Dumper; my %hash = ( cl_ip => 209890 ); my $json = encode_json \%hash; print Dumper( \%hash ); print qq($json\n); __END__ $VAR1 = { 'cl_ip' => 209890 }; {"cl_ip":209890}

    Update:

    I worry a bit about this. The OP wrote:

    "...some strings that were supposed to be converted to integers are still strings...So a data dump looks good: 'cl_ip' => 209889, But there's a string in the json file for this key: "cl_ip":"209889"..."

    From the JSON::XS manual:

    "...Its primary goal is to be correct..."

    The OP expects that the value of cl_ip is an integer after encoding, right?

    In my example using JSON::XS the OP gets what he wants (integer).

    IMHO JSON::XS works as designed - the result is what the OP expected.

    If i still miss something: thanks for any advice.

    I hope i didn't miss something. Regards Karl

    «The Crux of the Biscuit is the Apostrophe»

      perlnumber
      use JSON qw/ to_json from_json /;
      use Devel::Peek qw/ Dump /;
      my $q = 3;
      print "$q\n";
      Dump( $q );
      print to_json( { a => 3, qw/ b 3 q/, $q } );
      __END__
      3
      SV = PVIV(0x9a3778) at 0x99b524
        REFCNT = 1
        FLAGS = (PADMY,IOK,POK,pIOK,pPOK)
        IV = 3
        PV = 0xad23bc "3"\0
        CUR = 1
        LEN = 12
      {"a":3,"q":"3","b":"3"}
      "a" gets 3 the number, b gets 3 the string , q becomes the 3 string

      Hi Karl, I haven't installed JSON::XS yet (don't want to install dependencies yet) - could you try this out?

      my %hash; $hash{'cl_ip'} = "29988" + 0;
      I think the value is treated as a string at some point, perhaps when I search and replace any non-digit character. Thanks, Rachel

        "...could you try this out?"

        Why not, nice invitation:

        karls-mac-mini:monks karl$ perl -MData::Dumper -e '$hash{'cl_ip'} = "2 +9988" + 0;print Dumper(\%hash);'$VAR1 = { 'cl_ip' => 29988 };

        But: so what ;-)

        Update:

        D'oh! Mille Regretz!

        #!/usr/bin/env perl + use JSON::XS; use Data::Dumper; my %hash = ( cl_ip => 209890 ); my $json = encode_json \%hash; print Dumper( \%hash ); print qq($json\n); $hash{ cl_ip } += 0; $json = encode_json \%hash; print Dumper( \%hash ); print qq($json\n); __END__ karl-mac-mini:monks karl$ ./json.pl + $VAR1 = { + 'cl_ip' => 209890 + }; + {"cl_ip":209890} + $VAR1 = { + 'cl_ip' => 209890 + }; + {"cl_ip":209890}

        Update2:

        #!/usr/bin/env perl + use JSON::XS; use Data::Dumper; my %hash = ( cl_ip => 209890 ); my $json = encode_json \%hash; print Dumper( \%hash ); print qq($json\n); $hash{ cl_ip } += 0; $json = encode_json \%hash; print Dumper( \%hash ); print qq($json\n); $hash{ cl_ip } = "209890"; $json = encode_json \%hash; print Dumper( \%hash ); print qq($json\n); __END__ $VAR1 = { 'cl_ip' => 209890 }; {"cl_ip":209890} $VAR1 = { 'cl_ip' => 209890 }; {"cl_ip":209890} $VAR1 = { 'cl_ip' => '209890' }; {"cl_ip":"209890"}

        I'll give it up for tonight before i produce more shit...

        Update3:

        I'll give it up...

        I don't:

        #!/usr/bin/env perl use JSON::XS; use Data::Dumper; use strict; use warnings; my %hash = ( cl_ip => 209890 ); print Dumper( \%hash ); print qq(\n); my $json = encode_json \%hash; print qq($json\n\n); #------------------------------ $hash{cl_ip} += 0; print Dumper( \%hash ); print qq(\n); $json = encode_json \%hash; print qq($json\n\n); #------------------------------ $hash{cl_ip} = "209890"; print Dumper( \%hash ); print qq(\n); $hash{cl_ip} += 0; print Dumper( \%hash ); print qq(\n); $json = encode_json \%hash; print qq($json\n\n); __END__ karl-mac-mini:monks karl$ ./json.pl $VAR1 = { 'cl_ip' => 209890 }; {"cl_ip":209890} $VAR1 = { 'cl_ip' => 209890 }; {"cl_ip":209890} $VAR1 = { 'cl_ip' => '209890' }; $VAR1 = { 'cl_ip' => 209890 }; {"cl_ip":209890}

        My best regards, Karl

        «The Crux of the Biscuit is the Apostrophe»

Re: String to Integer, for json file
by Anonymous Monk on Dec 12, 2013 at 09:50 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1066762]
Approved by vinoth.ree
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (4)
As of 2024-03-29 10:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found