splitting the string as name, value pair in perl - perl

Suppose i have string result in json format as below.
{ "errorcode": 0, "message": "Done", "login": [ { "session_timeout": "1800", "token": "1370907977", "sessionid": "##F7A7E49F7FCFF35D3F821201CBF2F7CB5937E4AC99BF2AF74B508A1C8B3F", "username": "" } ] }
How can get a hash table from this like,
hash[errorcode] = 0;
hash[message] = Done;
PS: without using any additional modules and using simple string functions.

Use JSON module for parsing json structures to perl
use strict;
use warnings;
use JSON;
my $json_text = q({ "errorcode": 0, "message": "Done", "login": [ { "session_timeout": "1800", "token": "1370907977", "sessionid": "##F7A7E49F7FCFF35D3F821201CBF2F7CB5937E4AC99BF2AF74B508A1C8B3F", "username": "" } ] });
my $href = decode_json($json_text);
print $href->{errorcode}, $href->{message}, "\n";

I suppose that the non-module solution would be to cut and paste the relevant code from an existing module.
But that would be a terrible idea. Far better to just install the module.

Related

Getting extra variable in XML to JSON conversion using perl

My Program is giving extra variable $t in output. Can anyone help me on this?
use XML::XML2JSON;
xml content
my $XML = '<file><sno>1</sno><process>VALID</process><validation_type>C</validation_type><file_type>HTML</file_type><line>2</line><column>78</column><status>0</status><type>Warning</type><code>001</code><rule>aligning content.</rule><desc>Check that non-breaking space.</desc></file>';
my $XML2JSON = XML::XML2JSON->new();
my $JSON = $XML2JSON->convert($XML);
print $JSON;
Output - Extra variable is coming $t
{
"#encoding": "UTF-8",
"#version": "1.0",
"file": {
"status": {
"$t": "0"
},
"rule": {
"$t": "aligning content."
},
"validation_type": {
"$t": "C"
},
"process": {
"$t": "VALID"
},
"sno": {
"$t": "1"
},
"file_type": {
"$t": "HTML"
},
"desc": {
"$t": "Check that non-breaking space."
},
"type": {
"$t": "Warning"
},
"code": {
"$t": "001"
},
"line": {
"$t": "2"
},
"column": {
"$t": "78"
}
}
}
Expected output is:
{
"sno": "1",
"process": "VALID",
"validation_type": "C",
"file_type": "HTML",
"line": "2",
"column": "78",
"status": "0",
"type": "Warning",
"code": "001",
"rule": "aligning content.",
"desc": "Check that non-breaking space."
}
The $t is content key as mentioned in the XML::XML2JSON documentation.
If your intention is to convert from XML to JSON, I would recommend to use XML::Simple and later you can encode using JSON.pm.
Code below:
#!/usr/bin/perl
use strict;
use warnings;
use JSON;
use XML::Simple;
#Create an object
my $xmlSimple = new XML::Simple;
my $XML = '<file><sno>1</sno><process>VALID</process><validation_type>C</validation_type><file_type>HTML</file_type><line>2</line><column>78</column><status>0</status><type>Warning</type><code>001</code><rule>aligning content.</rule><desc>Check that non-breaking space.</desc></file>';
#either we can pass a variable or a xml file which contains xml data
my $dataXML = $xmlSimple->XMLin($XML);
my $jsonString = encode_json($dataXML);
print $jsonString;
Output:
{
"process":"VALID",
"line":"2",
"column":"78",
"type":"Warning",
"file_type":"HTML",
"sno":"1",
"status":"0",
"rule":"aligning content.",
"code":"001",
"desc":"Check that non-breaking space.",
"validation_type":"C"
}

How to append web request results in a while loop

I need to call an API and loop through the various pages of results that are returned and append them all to one object.
I've tried the code below. Generally += works when appending to a powershell object, but no luck this time.
Note: URI and Get are both functions that are defined elsewhere. They work as expected elsewhere in the code.
$min=1
$max=2
while ($min -le $max){
$url= URI "tasks?page=$min"
$x=Get $url
if($min=1){
$response=$x
}
else{
$response+=$x
}
$min=$min+1
}
sample response (converted to json):
"value": [
{
"task_id": 17709655,
"project_id": 1928619,
"start_date": "2019-04-11",
"end_date": "2019-11-29",
"start_time": null,
"hours": 1.5,
"people_id": 17083963,
"status": 2,
"priority": 0,
"name": "",
"notes": "",
"repeat_state": 0,
"repeat_end_date": null,
"created_by": 331791,
"modified_by": 0,
"created": "2019-04-12 00:39:30.162",
"modified": "2019-04-12 00:39:30.162",
"ext_calendar_id": null,
"ext_calendar_event_id": null,
"ext_calendar_recur_id": null
},
{
"task_id": 17697564,
"project_id": 1928613,
"start_date": "2019-10-08",
"end_date": "2019-10-08",
"start_time": null,
"hours": 8,
"people_id": 17083966,
"status": 2,
"priority": 0,
"name": "",
"notes": "",
"repeat_state": 0,
"repeat_end_date": null,
"created_by": 327507,
"modified_by": 0,
"created": "2019-04-11 16:10:22.969",
"modified": "2019-04-11 16:10:22.969",
"ext_calendar_id": null,
"ext_calendar_event_id": null,
"ext_calendar_recur_id": null
}
],
"Count": 2
}```
Assuming you want the output to be an array, I'd write your code like this:
$min=1
$max=2
$response = foreach ($Page in $min..$max) {
$url = URI "tasks?page=$Page"
Get $url
}
This is the generally preferred method, because both Strings and Arrays have fixed lengths in .Net and therefore PowerShell.
Here, $response[0] should be the first response, $response[1] the second, etc.
If the above doesn't work for you, then my first guess would be that the output of Get isn't a string.
If you're expecting $response to be a single valid JSON string containing all the responses, then my response is "JSON doesn't work that way." You'll have to parse each JSON response to objects (hint: ConvertFrom-Json) combine them, and then possibly convert them back to JSON (ConvertTo-Json). Note that .Net's native dialect of JSON doesn't match the rest of the Internet's dialect of JSON, particularly with dates (though it looks like your dates here are strings). You may want to use JSON.Net, which I believe does match the common Internet dialect.
You may be able to combine $response like this:
$CombinedResponse = '[' + ($response -join ',') + ']'
But I don't know how well that's going to work if you then try to parse that as JSON.

Accessing parent level using Data::Visitor::Callback (Perl)

This is a long-shot, but are there any perl developers out there who know anything about Data::Visitor::Callback?
I have a complex data structure that I am traversing. Each time I find a hash that has a 'total' key, I need to build up a URL. I have some of the data that I need to create these URLs but some of the data comes from higher up in the structure.
I don't think I can access the levels above and that makes it impossible to build my URLs. I only just realised that I needed data from higher up the structure.
If I can't make Data::Visitor::Callback work for me, then it means rolling my own traversal code - which is a pain.
Data I am traversing is converted from the following JSON (the "count" keys are renamed to "total" as part of the conversion process):
[
{
"field": "field_name",
"value": "A",
"count": 647,
"pivot": [
{
"field": "field_name",
"value": "B",
"count": 618,
"pivot": [
{
"field": "field_name",
"value": "C1",
"count": 572
},
{
"field": "field_name",
"value": "C2",
"count": 266
},
{
"field": "field_name",
"value": "C3",
"count": 237
}
]
},
...
Once I get to the deepest level (C), I need both A and B values in order to construct my URLs.
Because Data::Visitor::Callback is acting on each leaf independently, I'm not sure that it 'knows' where in the structure it is.
All help very much appreciated.
Thanks.
Given the JSON you posted is in the variable $json_string, the following code uses recursion to add the parents to all the children in the hash key parent, that way you can access the parents in your code.
use strict;
use warnings;
use JSON;
my $data = decode_json($json_string);
add_parent_to_children($_) for #$data;
sub add_parent_to_children {
my $node = shift;
my $parent = shift;
$node->{parent} = $parent if $parent;
if ($node->{pivot}) {
add_parent_to_children($_, $node) for #{$node->{pivot}};
}
}
Demo:
my $c3 = $data->[0]{pivot}[0]{pivot}[2];
print "$c3->{value}\n"; # prints C3
print "$c3->{parent}{value}\n"; # prints B
print "$c3->{parent}{parent}{value}\n"; # prints A

How to remove the curly braces and string from JSON file using Perl

{
"ticket": {
{
"id":"01",
"language": "Java",
"edition": "third",
"author": "Herbert Schildt"
},
{
"id":"07",
"language": "C++",
"edition": "second"
"author": "E.Balagurusamy"
}
}
,
"edition": "third",
"author": "Herbert Schildt"
}
That's my JSON file. I want to remove from file starting part {"ticket":
and ending part ,"edition": "third", "author": "Herbert Schildt" }.
Finally output I want like this:
{
"id":"01",
"language": "Java",
"edition": "third",
"author": "Herbert Schildt"
},
{
"id":"07",
"language": "C++",
"edition": "second"
"author": "E.Balagurusamy"
}
}
Note
Don't use regular expression, using only JSON Perl.
update
#!/usr/bin/perl
use JSON;
use Data::Dumper;
use Getopt::Long;
my($infile);
GetOptions('inFile=s' => \$infile);
my $json;
{
local $/;
open my $fh, "<", "$infile";
$json = <$fh>;
close $fh;
}
my $text = decode_json($json);
I have done this up to decode, but how to remove the starting and ending parts?
Assuming the syntax errors in your JSON file are by accident and fixing it with a comma and an array structure, this works:
#!/usr/bin/env perl
use strict;
use warnings;
use JSON;
my $json = do {
local $/;
<DATA>;
};
my $data = decode_json($json);
my $data2 = $data->{ticket};
my $json2 = encode_json($data2);
print $json2, "\n";
__DATA__
{
"ticket": [
{
"id":"01",
"language": "Java",
"edition": "third",
"author": "Herbert Schildt"
},
{
"id":"07",
"language": "C++",
"edition": "second",
"author": "E.Balagurusamy"
}
],
"edition": "third",
"author": "Herbert Schildt"
}
Prints out:
[{"language":"Java","edition":"third","author":"Herbert Schildt","id":"01"},{"language":"C++","edition":"second","author":"E.Balagurusamy","id":"07"}]

what is regular expression for matching single line with multi match?

$str = "Data = [ {"name": "test","Address": "UK" "currency": "£" },{"name": "test2","Address": "US" "currency": "$" },{"name": "test","Address": "eur" "currency": "E" }
I want to display all address
its not multi line string . It all a single string
Please help on this
Thanks ,
TREE J
Your string is JSON! Treat it as such!
edit: I'm an idiot and can't tell when a question is tagged as perl instead of PHP :-) Link ammended.
This should work:
while ($str =~ /\"Address\":\S+\"(.*?)\"/g) {
print "Address = $1\n";
}
You do it by using the right tool for the job. In this case you fix the corrupt JSON with a regex and then use JSON to get the data:
#!/usr/bin/perl
use strict;
use warnings;
use JSON;
my $input = <DATA>;
my ($json) = $input =~ /DATA = (.*)/;
my $data = decode_json $json;
for my $record (#$data) {
print "$record->{name} has address $record->{Address}\n";
}
__DATA__
DATA = [ {"name": "test", "Address": "UK", "currency": "£" }, {"name": "test2", "Address": "US", "currency": "$" }, {"name": "test", "Address": "eur", "currency": "E" } ]
something like:
my $str = q(Data = [ {"name": "test","Address": "UK" "currency": "£" },{"name": "test2","Address": "US" "currency": "$" },{"name": "test","Address": "eur" "currency": "E" });
my #addresses = $str =~ /"Address":\s*"([^"]*)"/g;
print "#addresses\n";
HTH,
Paul
(PS: post real code, not pseudo code...)