I have a problem.
For a mistake I have a lot of not valid JSON strings like this:
{
"d": {
"results": [
{
"__metadata": {
"uri": "https://api.datamarket.azure.com/Data.ashx/Bing/Search/Web?Query=u0027non supporting iframesu0027&Market=u0027it-ITu0027&Adult=u0027Offu0027&Options=u0027DisableLocationDetectionu0027&WebSearchOptions=u0027DisableQueryAlterationsu0027&$skip=0&$top=1",
"type": "WebResult"
},
"ID": "7858fc9f-6bd5-4102-a835-0fa89e9f992a",
"Title": "something good",
"Description": "something "WRONG" here!",
"DisplayUrl": "www.devx.com/Java/Article/27685/1954",
"Url": "http://www.devx.com/Java/Article/27685/1954"
}
],
"__next": "https://api.datamarket.azure.com/Data.ashx/Bing/Search/Web?Query=u0027non%20supporting%20iframesu0027&Market=u0027it-ITu0027&Adult=u0027Offu0027&Options=u0027DisableLocationDetectionu0027&WebSearchOptions=u0027DisableQueryAlterationsu0027&$skip=50"
}
}
As you can see the field Description contains a bad string (" into "), so I'm not able to parse the json using php's json_decode, infact it returns NULL.
I've 1 million of wrong json, much more big than this (10 times).
How can I do in php?
In your case you could exploit the fact that strings in json could not be over a line. That is a snappy point to grab with s multi-line aware search and replace with a regular expression function like preg_match_callback in PHP.
/^\s+"[a-z_"]+": "([^"]*".*)",?$/mi
Whitespace at the beginning of the line; member-name in form of a valid name (only characters and underscore here) as a string; the : and then the broken string until the end of the line optionally followed by a comma ,?.
This regex already matches only invalid lines. However if your json also contains a valid string with \" inside, this regex does not really work.
So it's also good to place some checks that the replacement would do what it is intended.
$like = '... json-like but broken json string as in question ...';
// Fixing #1: member strings containing double-quotes on the same line.
$fix1Pattern = '/^(\s+"[a-z_]+": ")([^"]*".*)(",?)$/mi';
$fix1Callback = function ($matches) {
list($full, $prefix, $string, $postfix) = $matches;
$fixed = strtr($string, ['"' => '\"']);
if (!is_string(json_decode("\"$fixed\""))) {
throw new Exception('Fix #1 did not work as intended');
}
return "$prefix$fixed$postfix";
};
// apply fix1 onto the string
$buffer = preg_replace_callback($fix1Pattern, $fix1Callback, $like);
// test if it finally works
print_r(json_decode($buffer));
Keep in mind that this is limited. You might need to learn about regular expressions first which is a world of it's own. But the principle is often very similar: You search the string for the patterns that are the broken parts and then you do some string manipulation to fix these.
If the json string is much more broken, then this needs even more love, probably not to be easily solved with a regular expression alone.
Exemplary output for the code-example and the data provided:
stdClass Object
(
[d] => stdClass Object
(
[results] => Array
(
[0] => stdClass Object
(
[__metadata] => stdClass Object
(
[uri] => https://api.datamarket.azure.com/Data.ashx/Bing/Search/Web?Query=u0027non supporting iframesu0027&Market=u0027it-ITu0027&Adult=u0027Offu0027&Options=u0027DisableLocationDetectionu0027&WebSearchOptions=u0027DisableQueryAlterationsu0027&$skip=0&$top=1
[type] => WebResult
)
[ID] => 7858fc9f-6bd5-4102-a835-0fa89e9f992a
[Title] => something good
[Description] => something "WRONG" here!
[DisplayUrl] => www.devx.com/Java/Article/27685/1954
[Url] => http://www.devx.com/Java/Article/27685/1954
)
)
[__next] => https://api.datamarket.azure.com/Data.ashx/Bing/Search/Web?Query=u0027non%20supporting%20iframesu0027&Market=u0027it-ITu0027&Adult=u0027Offu0027&Options=u0027DisableLocationDetectionu0027&WebSearchOptions=u0027DisableQueryAlterationsu0027&$skip=50
)
)
Related
I have a PHP array as follows:
Array
(
[Caller] => EFLwebsite
[CaseDetails] => Array
(
[Description] => This is a Site Readiness case.
[SAPCustomerCode] => 1001140090
[ProductNumber] => GWPDREVIV00000
[CustomerAssetSerialNumber] => 000000000418005207
[RequestedDate] => 2021/01/06
[RequestedTime] => 10:00:45
[BP] => CRM Test User
)
)
I need to convert the above array into json as follows:
{
"Caller":"EFLwebsite",
"CaseDetails":"{\"Description\":\"This is a Site Readiness case.\",\"SAPCustomerCode\":\"0100301500\",\"ProductNumber\":\"GWPDFCOND00000\",\"CustomerAssetSerialNumber\":\"000000000418005207\",\"RequestedDate\":\"2021\/01\/06\",\"RequestedTime\":\"23:54:12\",\"BP\":\"CRM Test User\"}"
}
I am using addslases() after json_encode but it returns as follows:
{
\"Caller\":\"EFLwebsite\",
\"CaseDetails\":{\"Description\":\"This is a Site Readiness case.\",\"SAPCustomerCode\":\"1001140090\",\"ProductNumber\":\"GWPDREVIV00000\",\"CustomerAssetSerialNumber\":\"000000000418005207\",\"RequestedDate\":\"2021\\/01\\/06\",\"RequestedTime\":\"10:00:45\",\"BP\":\"CRM Test User\"}
}
I need to add the slashes only to the second value which is CaseDetails
I also tried encoding the subarray separately and adding slashes as a string, but it is adding more slashes again.
I also have no idea why you would want to do this, but this should do the trick:
$array = [
"Caller" => "EFLwebsite",
"CaseDetails" => [
"Description" => "This is a Site Readiness case.",
"SAPCustomerCode" => "1001140090"
]
];
// first convert case details to json
$array["CaseDetails"] = json_encode($array["CaseDetails"]);
echo "<pre>";
print_r(json_encode($array)); // then convert everything to json
echo "</pre>";
This returns:
{"Caller":"EFLwebsite",
"CaseDetails":"{\"Description\":\"This is a Site Readiness case.\",\"SAPCustomerCode\":\"1001140090\"}"}
Using heredoc string with php. Docs
Heredoc text behaves just like a double-quoted string, without the double quotes. This means that quotes in a heredoc do not need to be escaped, but the escape codes listed above can still be used. Variables are expanded, but the same care must be taken when expressing complex variables inside a heredoc as with strings.
$case = addslases(json_encode($array['CaseDetails']));
$json = <<<EOT
{ "Caller": "{$array['Caller']}", "CaseDetails": {$case} }
EOT;
echo $json;
I have a below array:
Array
(
[0] => CLICK
[1] => CSC
)
After json_encode I got below one.
"["CLICK","CSC"]"
How to convert this into "[\"CLICK\",\"CSC\"]" this.
Any one help.
Some info was missing which I got after discussion.
They are manually replacing a lot of characters before returning json. Out of them they also include [ => "[ and ] => ]" due to their backend implications.
A simple json_encode was solution for this along with skipping those character replacement for specific this key.
Source:
<?php
$arr = [
"CLICK", "CSC"
];
echo json_encode(json_encode($arr)) . "\n";
Result:
"[\"CLICK\",\"CSC\"]"
I created a REST API using Laravel (Lumen). Basically I'm taking some values from database and need to do some functions. Here's the problem.
There's a field called web_data in my result set. It's Perl code. This is how it looks when I query the database using normal SQL editor like phpmyadmin and workbench.
{"caption" => "Genes (Comprehensive set from GENCODE 26)","colour_key" => "[biotype]","default" => {"MultiBottom" => "collapsed_label","MultiTop" => "gene_label","alignsliceviewbottom" => "as_collapsed_label","contigviewbottom" => "transcript_label","contigviewtop" => "gene_label","cytoview" => "gene_label"},"key" => "ensembl","label_key" => "[biotype]","multi_name" => "GENCODE 26 Comprehensive gene set","name" => "Comprehensive Gene Annotations from GENCODE 26"}
It's very clear and nothing wrong. But when I get the same result via my REST API, I'm getting the following output. It has many "\" symbols. Here's that output.
{\"caption\" => \"Genes (Comprehensive set from GENCODE 26)\",\"colour_key\" => \"[biotype]\",\"default\" => {\"MultiBottom\" => \"collapsed_label\",\"MultiTop\" => \"gene_label\",\"alignsliceviewbottom\" => \"as_collapsed_label\",\"contigviewbottom\" => \"transcript_label\",\"contigviewtop\" => \"gene_label\",\"cytoview\" => \"gene_label\"},\"key\" => \"ensembl\",\"label_key\" => \"[biotype]\",\"multi_name\" => \"GENCODE 26 Comprehensive gene set\",\"name\" => \"Comprehensive Gene Annotations from GENCODE 26\"}
Can you please tell me what's the reason for this? Is this an issue with PHP or something like that ?
And also I have another issue. This is Perl code containing "=>" symbols to seperate values. I need to convert this into a JSON object using PHP. Is that possible ?
Need to convert like following object.
{ "caption" : "Genes (Comprehensive set from GENCODE 26)", "colour_key" : "[biotype]", "default" : { "MultiBottom" : "collapsed_label" ...
This is the php code i'm using to create the REST output using SQL data.
public function testDualDatabaseConnection()
{
$testGene = DB::connection('mysql2')->select('select a.analysis_id, logic_name, ad.description, ad.display_label, ad.web_data FROM ( select distinct(analysis_id) as analysis_id from gene ) as a join analysis on (a.analysis_id = analysis.analysis_id) join analysis_description as ad on (analysis.analysis_id = ad.analysis_id) where ad.displayable = :wow1', ['wow1' => "1"]);
return response()->json($testGene);
}
And also this is the full JSON output i'm getting via REST API.
https://gist.github.com/chanakaDe/0d1e5916d8bc788bb101afa9b92dc9cd
In this response, you can see "web_data", that's also the part I need to convert to JSON again.
If on the off chance you really do have
{\"caption\" => \"Genes ...\", ...}
Then you have a JSON fragment, and the first you thing you need to do is turn it into a complete JSON document so it can be decoded.
$json_fragment_from_api = '{\"caption\" => \"Genes ...\", ...}';
$json_from_api = '{"result":"' . $json_fragment_from_api . '"}';
$response = json_decode($json_from_api, true);
$perl_code = $response["result"];
That said, I think it's far more likely that you only showed a portion of your actual input. You're far more likely to have received something that looks more like
{ "result": "{\"caption\" => \"Genes ...\", ...}" }
Since you already have a complete JSON document, simply start by decoding it.
$json_from_api = '{ "result": "{\"caption\" => \"Genes ...\", ...}" }';
$response = json_decode($json_from_api, true);
$perl_code = $response["result"];
At this point, you have the value from the database.
{"caption" => "Genes ...", ...}
That value is Perl code. More specifically, it's surely Perl code that was produced by Data::Dumper. This is going to be hard to convert into JSON.
You could use the following, but it won't handle everything:
$desired_json = str_replace(' =>', ':', $perl_code);
Here are some things it won't handle:
Undefined values
Strings containing =>
Strings containing $
Strings containing #
Strings containing non-ASCII or some non-printable characters.
As shown here:
$ perl -e'
use feature qw( say );
use Data::Dumper qw( Dumper );
local $Data::Dumper::Useqq = 1;
local $Data::Dumper::Terse = 1;
local $Data::Dumper::Indent = 0;
say(Dumper({ x => undef }));
say(Dumper({ x => " => " }));
say(Dumper({ x => q{$} }));
say(Dumper({ x => q{#} }));
say(Dumper({ x => "\x7F" }));
'
{"x" => undef} # Gives {"x": undef} instead of {"x": null}
{"x" => " => "} # Gives {"x": ": "} instead of {"x": " => "}
{"x" => "\$"} # Gives {"x": "\$"} instead of {"x": "$"}
{"x" => "\#"} # Gives {"x": "\#"} instead of {"x": "#"}
{"x" => "\177"} # Gives {"x": "\177"} instead of {"x": "\u007f"}
Not sure where that escaping happens (if you can, give some more details)
But, try to replace => with : and \" with " and you'll have yourself a valid json.
$string = '{\"caption\" => \"Genes (Comprehensive set from GENCODE 26)\",\"colour_key\" => \"[biotype]\",\"default\" => {\"MultiBottom\" => \"collapsed_label\",\"MultiTop\" => \"gene_label\",\"alignsliceviewbottom\" => \"as_collapsed_label\",\"contigviewbottom\" => \"transcript_label\",\"contigviewtop\" => \"gene_label\",\"cytoview\" => \"gene_label\"},\"key\" => \"ensembl\",\"label_key\" => \"[biotype]\",\"multi_name\" => \"GENCODE 26 Comprehensive gene set\",\"name\" => \"Comprehensive Gene Annotations from GENCODE 26\"}';
$string = str_replace('\"','"', $string);
$string = str_replace('=>',':', $string);
$json = json_decode($string, true);
print_r($json);
You can check it out here: https://3v4l.org/UBmGA
Apparently this answer got more hate than i'd expect. Nevertheless, it did help OP and i'm sticking by it. In the end, this is what SO stands for.
I would like to know though... why so many downvotes? I do take constructive criticism well and would like to know how to improve future answers.
If there is 2 parameter in php function how to know which parameter is kept in first and another second.
This is a php function array_search($needle,$array). This will search $needle in an array $array.
In array_slice($array, 2) slice is to be done in an array $array is first parameter.
In trim($string, 'abc') trim is to be done in string $string is a first parameter.
Is there any way to remember which parameter come first? I think we can remember function but remembering parameter also is not possible for all functions.
Thanks
Welcome to PHP ,
The likely most common complaint you get to hear about PHP is the
inconsistent and unclear naming of functions in the standard library,
as well as the equally inconsistent and unclear order of parameters.
Some typical examples:
// different naming conventions
strpos
str_replace
// totally unclear names
strcspn // STRing Complement SPaN
strpbrk // STRing Pointer BReaK
// inverted parameter order
strpos($haystack, $needle)
array_search($needle, $haystack)
so if you want to check (within your application and away from man pages)
as a work around to get around this, you may make use of Reflection collection in php :
for example:
function getFunctionInfo($functionName) {
$function = new ReflectionFunction($functionName);
return [
'name' => $function->getName(),
'parameters' => array_column($function->getParameters(), 'name'),
'numberOfParameters' => $function->getNumberOfParameters(),
'requiredParameters' => $function->getNumberOfRequiredParameters()
];
}
print_r(getFunctionInfo('explode'));
this will output:
Array (
[name] => explode
[parameters] => Array (
[0] => separator
[1] => str
[2] => limit
)
[numberOfParameters] => 3
[requiredParameters] => 2
)
and for live view: https://3v4l.org/T2Nad
the above quote had been quoted from : nikic.github.io
I'm trying to extract a specific value from json content . Here it is link with the json code http://www.ebayclassifieds.com/m/AreaSearch?jsoncallback=json&lat=41.1131514&lng=-74.0437521 As you may see the the code displayed is
json({items:[{url:"http://fairfield.ebayclassifieds.com/",name:"Fairfield"},{url:"http://newyork.ebayclassifieds.com/",name:"New York City"}],error:null});
I need to extract the first url which in this case is "http://fairfield.ebayclassifieds.com/" and its name value which is "Fairfield" , I could do it with regex but I would prefer to use json_decode. Unfortunately when I try to decode it doesn't work
$json = getContent("http://www.ebayclassifieds.com/m/AreaSearch?jsoncallback=json&lat=41.1131514&lng=-74.0437521");
$test = json_decode($json, true);
As danp already said, the returned JSON is enclosed in a function call (specified by jsoncallback=json). You cannot get rid of this totally but, just using AreaSearch?jsoncallback=&lat=41.1131514&lng=-74.0437521 removes at least the json at the beginning of the string and you can get rid of the brackets by:
$json = trim(trim($json), "();");
with gives:
{items:[{url:"http://fairfield.ebayclassifieds.com/",name:"Fairfield"},{url:"http://newyork.ebayclassifieds.com/",name:"New York City"}],error:null}
Unfortunately, the JSON string is not valid. The keys (items, url, ...) have to be enclosed in quotes ". You can easily check that you get a syntax error with json_last_error() (error code 4, JSON_ERROR_SYNTAX).
Update:
According to this question: Invalid JSON parsing using PHP , you can make the JSON string valid with:
$json = preg_replace('/(\w+):/i', '"\1":', $json);
This encloses the keys in quotes.
If the string would be valid, then you could generate an array via:
$a = json_decode($json, true);
which would give you:
Array
(
[items] => Array
(
[0] => Array
(
[url] => http://fairfield.ebayclassifieds.com/
[name] => Fairfield
)
[1] => Array
(
[url] => http://newyork.ebayclassifieds.com/
[name] => New York City
)
)
[error] =>
)
So you could get the first URL and name via $a['items'][0]['url'] and $a['items'][0]['name'] resp.
But I repeat, the JSON you get as response is not valid and you cannot parse it with json_decode() in its original form.
Its not valid JSON. The keys should be wrapped inside quotes.
You can validate your json using the excellent JSON Lint site.
This is a valid version of the data returned:
{
"items": [
{
"url": "http://fairfield.ebayclassifieds.com/",
"name": "Fairfield"
},
{
"url": "http://newyork.ebayclassifieds.com/",
"name": "New York City"
}
],
"error": "null"
}