0

I have a request that I make in an API using GET LWP::UserAgent, the data is returned as JSON, with up to two results at most as follows:

{
   "status":1,
   "time":1507891855,
   "response":{
      "prices":{
         "nome1\u2122":{
            "preco1":1111,
            "preco2":1585,
            "preco3":1099
         },
         "nome2":{
            "preco1":519,
            "preco2":731,
            "preco3":491
         }
      }
   }
}

Dump:

$VAR1 = {
  'status' => 1,
  'time' => 1507891855,
  'response' => {
                  'prices' => {
                                'nome1' => {
                                             'preco1' => 1111,
                                             'preco3' => 1099,
                                             'preco2' => 1585
                                           },
                                'nome2' => {
                                             'preco3' => 491,
                                             'preco1' => 519,
                                             'preco2' => 731
                                           }
                              }
                }
};

What I would like to do is:

Take this data and save it in a variable to make a comparison using if with another variable that already has the name stored. The comparison would be with name1 / name2 and if it is true with the other variable it would get preco2 and preco3 to print everything

My biggest problem in the case is that some of these names in JSON contain characters like (TradeMark) that comes as \u2122 (some cases are other characters), so I can not make the comparison with the name of the other variable that is already with the correct name

nome1™

If I could only save the JSON already "converted" the characters would help me with the rest.

Basically after doing the request for the API I want to save the contents in a variable already converting all \u2122 to their respective character (this is the part that I do not know how to do in Perl) and then using another variable to compare them names are equal to show the price

Thanks for the help and any questions please tell me that I try to explain again in another way.

Borodin
  • 126,100
  • 9
  • 70
  • 144
edufgimenez
  • 60
  • 1
  • 3
  • 9
  • 1
    Your tiny snippets of code don't make it clear at all what you're doing. What is `$nome1json` for example? Please add a [mcve] so we might better be able to help you find a solution to your problem. – Chris Turner Oct 13 '17 at 14:21
  • https://stackoverflow.com/questions/10708297/perl-convert-a-string-to-utf-8-for-json-decode – xxfelixxx Oct 13 '17 at 14:21
  • Basically after doing the request for the API I want to save the contents in a variable already converting all \ u2122 to their respective character (this is the part that I do not know how to do in Perl) and then using another variable to compare them names are equal to show the price. I'm sorry if I left the question vague. – edufgimenez Oct 13 '17 at 14:45
  • How do you currently convert the JSON data to the Perl data structure that you have dumped? Why has the `™` vanished? – Borodin Oct 13 '17 at 17:21

1 Answers1

0

If I understand correctly, you need to get the JSON that you receive in UTF8 format to an internal variable that you can process. For that, you may use JSON::XS:

use utf8;
use JSON::XS;

my $name = "nome1™";
my $var1 = decode_json $utf8_encoded_json_text;

# Compare with name in $name
if( defined $var1->{'response'}->{'prices'}->{$name} ) {
  # Do something with the name that matches
  my $match = $var1->{'response'}->{'prices'}->{$name};

  print $match->{'preco1'}, "\n";
}

Make sure you tell the Perl interpreter that your source is in UTF8 by specifying use utf8; at the beginning of the script. Then make sure you are editing the script with an editor that supports that format.

The function decode_json will return a ref to the converted value. In this case a hash ref. From there you work your way into the JSON.

If you know $name is going to be in the JSON you may omit the defined part. Otherwise, the defined clause will tell you whether the hash value is there. One you know, you may do something with it. If the hash values are a single word with no special characters, you may use $var1->{response}->{prices}->{$name}, but it is always safer to use $var1->{'response'}->{'prices'}->{$name}. Perl gets a bit ugly handling hash refs...

By the way, in JSON::XS you will also find the encode_json function to do the opposite and also an object oriented interface.

Javier Elices
  • 2,066
  • 1
  • 16
  • 25
  • Think that last `$name` should be `$match`? – Chris Turner Oct 13 '17 at 16:15
  • Yes, my mistake. Fixed. Thanks. – Javier Elices Oct 13 '17 at 16:18
  • @JavierElices This worked fine, however the data of the variable I need to compare are in a txt encoded in UTF-8, the data in the txt already has the characters (★, ™) some names are just pure texts with no characters, so the code that you passed can only assimilate the names when they are just pure texts, any tips? – edufgimenez Oct 14 '17 at 06:44
  • The converted text will be in UTF8. If your data is in UTF8 as well (a subset of Unicode), Perl should have no problem manipulating or comparing. Are you sure your data is in UTF8? If you print them to the same terminal, do they appear alike? – Javier Elices Oct 14 '17 at 08:30
  • The data that is in this txt is taken in another API, in this API the names that I need to compare are already "converted" with the symbols, that is, the variable my $name = "nome1 ™"; it actually comes from a txt as an array, but in this other API the names are already listed as follows: "name": "nome1 ™", not "name": "name \ u2122" as it is in the API case of the code you sent me , then when your code tries to compare the API data (if (defined $ var1 -> {'response'} -> {'prices'} -> {$ name}) {) they do not match. If so, how can I edit my post to try to explain it better? Thanks for help. – edufgimenez Oct 14 '17 at 18:41
  • A big trap in Perl is the way data enters and exits a script. The cure is to tell Perl explicitly what the format of the data is. If you are reading a text file, are you telling Perl that it is UTF8? Something like `open(my $fh, "<:encoding(UTF-8)", $filename)`. – Javier Elices Oct 14 '17 at 20:21
  • If you need to make sure you are reading your data in UTF8, you may want to ask a specific question about that or edit your question to show the code you are using to read all data in your script. – Javier Elices Oct 14 '17 at 20:25
  • @JavierElices It worked perfectly using `open(my $fh, "<:encoding (UTF-8)", $filename)`, before I was reading the txt using the module IO::All, `my @lines = io($filename)->slurp`, can I take advantage of you and ask you one last question? Although everything is working the program now appears with each request: "Wide character in print at C: /Strawberry/perl/lib/IO/Handle.pm line 420. I tried to use 'utf8' at the top of the program but it did not. Thanks again for all help. – edufgimenez Oct 15 '17 at 13:15
  • I tried to use `no warnings 'utf8'` at the top of the program but it did not work – edufgimenez Oct 15 '17 at 13:23
  • The error "Wide character in print" probably has to do with Perl not expecting your terminal to accept UTF8. As I said, you should tell Perl that all inputs and outputs are UTF8 explicitly. It is a pain because each type has its own trick. Try adding `binmode(STDOUT, ':encoding(UTF-8)');` at the beginning of your script to tell Perl to consider STDOUT as UTF8. – Javier Elices Oct 15 '17 at 13:25
  • Also, consider asking different questions. The answers you get in comments not directly related to your question will not help anyone else. – Javier Elices Oct 15 '17 at 13:26