Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW

Interpolating variables in JSON string

by reisinge (Friar)
on Jan 29, 2013 at 11:25 UTC ( #1015856=perlquestion: print w/replies, xml ) Need Help??
reisinge has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

I am authenticating through Rackspace API with the following code (using LWP):

sub authenticate { # Create a request my $req = HTTP::Request->new( POST => '' +); $req->content_type('application/json'); #my $json = '{"auth":{"RAX-KSKEY:apiKeyCredentials":{"username":"f +oo", "apiKey":"00000000000000000000000000000000"}}}'; my $json = quotemeta( {"auth":{"RAX-KSKEY:apiKeyCredentials":{"use +rname":$USERNAME, "apiKey":$API_KEY}}} ); $req->content( $json ); # Pass request to the user agent and get a response back my $res = $ua->request($req); # Check the outcome of the response if ( $res->is_success ) { # Do stuff ... } else { print $res->status_line, "\n"; } }

The problem is that I am not able to interpolate the variables in JSON string ($USERNAME and $API_KEY) - I am getting 400 BadRequest response. I have tried quotemeta (in the code snippet above), \Q and \E operators, escaping JSON double quotes with \.

The commented out $json line (with hard-coded credentials) works just fine.

We are what we repeatedly do. Excellence, then, is not an act but a habit. -- Will Durant (Aristotle)

Replies are listed 'Best First'.
Re: Interpolating variables in JSON string
by moritz (Cardinal) on Jan 29, 2013 at 11:34 UTC

    The proper way to create JSON strings is to first create a data structure in Perl that matches the desired output structure, and then run it through a JSON module like JSON or JSON::XS:

    use JSON qw/encode_json/; my $data = { auth => { "RAX-KSKEY:apiKeyCredentials" => { username => $USERNAME, apiKey => $API_KEY, }, }, }; my $json = encode_json($data);
Re: Interpolating variables in JSON string
by Corion (Pope) on Jan 29, 2013 at 11:28 UTC
Re: Interpolating variables in JSON string
by roboticus (Chancellor) on Jan 29, 2013 at 11:49 UTC


    I agree with the previous posters. However, it looks like you're just forgetting to put quotes around $USERNAME and $API_KEY. JSON is going to want quotes around string values, and you're just dropping them in without the quotes. You probably need:

    my $json = quotemeta( {"auth":{"RAX-KSKEY:apiKeyCredentials":{"usernam +e":"$USERNAME", "apiKey":"$API_KEY"}}} );

    So while this may get you going for now, just remember that it'll come back to bite you if you're not careful. Hence, the aforementioned suggestions.


    When your only tool is a hammer, all problems look like your thumb.

Re: Interpolating variables in JSON string
by muba (Priest) on Jan 29, 2013 at 13:52 UTC

    The line

    my $json = quotemeta( {"auth":{"RAX-KSKEY:apiKeyCredentials":{"use +rname":$USERNAME, "apiKey":$API_KEY}}} );
    makes no sense. The character : is only part of the Perl syntax in rather specific places, and this isn't one of them. I get a syntax error message for this line.

    The Perl equivalent of a JSON map is called a hash. Traditionally we use => to separate keys from their values, not :.

    my $json = quotemeta( {"auth" => {"RAX-KSKEY:apiKeyCredentials" => + {"username" => $USERNAME, "apiKey" => $API_KEY}}} );

    But even that would make little sense. That line would make the data structure, return a reference to it, try to quotemeta that reference, and store that in $json. So $json would end up being something like "HASH\(0x33c218\)". You don't need quotemeta here — you only need quotemeta when you're about to use a string inside a regular expressions and you're afraid that your string might have regex meta characters while you actually want to match them literally. What you do need is a real JSON module, like the good monks before me already suggested.

Re: Interpolating variables in JSON string
by Anonymous Monk on Jan 29, 2013 at 13:23 UTC
    It is definitely easier to use a JSON package, as noted, because this authentication request is only going to be the first of many requests that you will be sending to this host. Do as the Romans do ...

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1015856]
Front-paged by Arunbear
[Corion]: Of course, it's a 20% cut in the money I receive, while the work doesn't necessarily reduce at all, but my approach is to make the work take longer instead of fitting 5 days worth of work into 4
[holli]: 50% off all children coffins.
[Corion]: holli: Ooof :)
[hippo]: Cut should beless than 20% after tax, though. :-)
[Corion]: hippo: Yeah, but at least two years ago, it still was close enough to 20% cut
[Corion]: But I have a very positive experience with a four day workweek and a three day weekend. I can't easily go back though to full money.
[Corion]: That is easy without having to pay for a house, a wife or children though. If I had any of these, or any two of these, the decision wouldn't be that easy.
[ambrus]: wait. I understand no wife and children, but how do you not have to pay for a house?

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (10)
As of 2017-09-21 15:13 GMT
Find Nodes?
    Voting Booth?
    During the recent solar eclipse, I:

    Results (249 votes). Check out past polls.