Escaping slashes when decoding json php - php

I have a problem when returning a row from database that has a column type TEXT(in this case, column "details") which contains an array of JSON objects. Example:
{
productid: 1
shopid: 1
title: 'Product 1'
--> details: [{"name":"Brand name","value":"Brand value"},{"name":"Color","value":"blue"}]
. . .
}
Data inserted into database in columns of type TEXT are inserted like addslashes(json_encode($array_or_object)) to safely escape before insert.
When returning data, columns of type TEXT by function json_decode() and returned with no problem. Problem occurs when someone tries using single ' and double quotes " in details. Example:
details: [{"name":"\\\"test123\\\"","value":"\\\"test\\\" \\'test\\' \\\"test \\' test \\' t\\\"est"}]
Returned value looks like:
"details": [
{
"name": "\\\"test123\\\"",
"value": "\\\"test\\\" \\'test\\' \\\"test \\' test \\' t\\\"est"
}
],
I have more than one way of storing JSON data in database (as object, array of objects, array of arrays of objects,...), and I need a way to escape these backslashes.
Using stripslashes() on the string before using json_decode() does not work, it breaks the JSON.
Creating a recursive function works, but is not as pretty as I would like it to be. Example:
function decode_json($json) {
if (empty($json)) {
return $json;
}
if (is_string($json)) {
$json = json_decode($json, true);
}
foreach ($json as $key => $value) {
if (is_array($value)) {
$json[$key] = decode_json($value);
continue;
}
$json[$key] = stripslashes($value);
}
return $json;
}
Any help is appreciated.

json_encode already escape your string, you don't need to use addslashes()
Example:
$var = ["value" => "test'\""];
print_r(json_encode($var));
Result:
{"value":"test'\""}
And will be better to use PDO with bind parameters: https://www.php.net/manual/en/pdostatement.bindparam.php

and what exactly is the point of using a database, when storing the raw JSON?
decode first, then escape the values to insert - else you'll also escape all of the JSON delimiters,
which might subsequently cripple the whole input string and render it F.U.B.A.R.
PS: PDOStatement still requires PDO::quote() to escape the input properly.

Related

Decode only the first level of a JSON in PHP

The question
I have a JSON string which I would like to decode. However, I only want the first level to be decoded, the rest of the JSON should stay as string values instead of nested arrays.
Using a similar technique, the generated array (with nested string values) should be parsed back to a JSON string. When using these decode and encode in succession the result should be the original JSON string.
Short and simple, right?
I would also rather not interpret the nested values of the JSON, as those may or may not be valid JSON. If there is no way around this, then so be it.
Example
Please note that all these slashes are just to keep it a valid PHP string, they are not part of the input. There are no escaped quotes in the input.
When a JSON string like this is put in:
"{
\"foo\": \"bar\",
\"nested\": {
\"nested_key\": \"nested_value\"
},
\"another_top_level_key\": \"some_useful_value\"
}"
This should be the output:
[
"foo" => "bar",
"nested" => "{ \"nested_key\": \"nested_value\" }",
"another_top_level_key" => "some_useful_value"
]
When using var_dump, it should look like this:
array(3) {
["foo"]=>
string(3) "bar"
["nested"]=>
string(32) "{ "nested_key": "nested_value" }"
["another_top_level_key"]=>
string(17) "some_useful_value"
}
Pay attention to the fact that when using var_dump, the quotes are not escaped and thus no slashes exist in the string (the nested quotes are not escaped).
When that array is run through the second function (the encoder), the original JSON string should be returned.
Things I've tried:
I tried setting the $depth of json_decode() to 1. This, however, only throws exceptions when the limit has been reached.
I tried decoding the whole string using json_decode() and then looping over the top-level key-value pairs to run json_encode() over any value that is an array (which should indicate a nested value). The end result was fine at first, but when converting back to a JSON string it escaped the double quotes with slashes. In that case, the end result isn't the same as the original, as the end result includes slashes.
Notes
Even though this question has a very similar title to this one, that one doesn't actually contain answers for its title. There is only an answer on how to transform the invalid JSON string to a valid JSON.
I'd rather not use any RegEx, as that just makes my life more complex than it needs to be ;). But if it can't be avoided, then that's life I guess.
As requested by deceze:
$jsonString = "{ \"foo\": \"bar\", \"nested\": { \"nested_key\": \"nested_value\" }, \"another_top_level_key\": \"some_useful_value\" }";
$decoded = json_decode($jsonString, true);
foreach ($decoded as $key => $value) {
if (is_array($value)) {
$decoded[$key] = json_encode($value);
}
}
$encoded = json_encode($decoded);
var_dump($encoded);
The result is this:
string(102) "{"foo":"bar","nested":"{\"nested_key\":\"nested_value\"}","another_top_level_key":"some_useful_value"}"
Which means that in the end, it did escape the quotes, which is something I cannot accept :(.
Use a function to check when you have an element as array then convert back to json:
<?php
$json = "{
\"foo\": \"bar\",
\"nested\": {
\"nested_key\": \"nested_value\"
},
\"multinested\": {
\"multinested_key\": {
\"multinested_key\": \"nested_value\"
}
},
\"another_top_level_key\": \"some_useful_value\"
}";
$array = json_decode($json, true);
foreach($array as &$item) {
if (is_array($item)) {
$item = json_encode($item);
}
}
print_r($array);
Output:
Array
(
[foo] => bar
[nested] => {"nested_key":"nested_value"}
[multinested] => {"multinested_key":{"multinested_key":"nested_value"}}
[another_top_level_key] => some_useful_value
)
The trick is to use the decode twice:
$array = json_decode(json_decode($json, true), true);
print_r($array);

Correct way of adding text + php variable in json string?

I am struggling a bit to find the correct way of adding a php variable in my json string, with text added just in front of the variable. This is what I have got so far...
$postData = '
{
"message": "Web order '.$order_number.'"
}
';
When I look at the printout there is a line break just after "Web order", but otherwise nothing seems to go wrong... is this the way to do it?
If you want to use json string, then make sure you have properly use your values in your array.
Example:
<?
$order_number = 1;
$yourArray = array('message'=>"Web order ".$order_number);
echo json_encode($yourArray);
?>
Result:
{"message":"Web order 1"}
Here, i am using an array for your data $yourArray and then use json_encode() for json string.
DEMO
Instead of concatenate string, use sprintf()
Dealing directly with Json can become very harmful quickly. Prefer to use array then json_encode instead.
in your case, here is a simple example:
$message = sprintf('Web order %s', $order_number)
$postData = [
'message' => $message
];
$json = json_encode($postData);

loop through JSON string in php

I have a json string derived from MySQL query using GROUP_CONCAT (which returns STRING).
Here's JSON string as field portfolios:
[
{name:"Branch GBD_1.pdf", img_path:"1333752771.pdf"},
{name:"Doc.pdf", img_path:"2020107119.pdf"},
{name:"COK.pdf", img_path:"264860069.pdf"}
]
Now in php, I tried to decode the field and loop through it, but I am not being able to.
foreach($records as $r)
{
$varArray = json_decode($r['portfolios'], true);
foreach($varArray as $que)
{
echo $que['name'].' '.$que['img_path'];
echo '<br/>';
}
}
How do I break or convert the variable into loop-able object?
$varArray is not an array because your json string is not valid json. The keys need to be wrapped in doublequotes.
[
{"name":"Branch GBD_1.pdf", "img_path":"1333752771.pdf"},
{"name":"Doc.pdf", "img_path":"2020107119.pdf"},
{"name":"COK.pdf", "img_path":"264860069.pdf"}
]

Prevent strtotime being encoded as string by json_encode

I am building data for a status dashboard that uses Highcharts.js, and loading it with ajax, however when using json_encode my timestamps are getting quoted, which means Highcharts chokes on them.
The code is:
$responseData = array();
foreach ($monitors as $monitor => $data) {
foreach (array_reverse($data['responsetime']) as $responsetime) :
$responses[] = array(strtotime($responsetime['datetime'])*1000 => $responsetime["value"]);
endforeach;
$responseData[] = array('name' => $data['friendlyname'], 'data' => $responses);
}
$responseData = json_encode($responseData,JSON_NUMERIC_CHECK);
Using JSON_NUMERIC_CHECK prevents problems with the value, but the key (a timestamp) gets quoted still.
Example output:
[{"name":"Series 1","data":[{"1432933860":1622},{"1432935660":1458},{"1432937461":1388}]},{"name":"Series 2","data":[{"1432933860":1622},{"1432935660":1458},{"1432937461":1388}]}]
Desired output:
[{"name":"Series 1","data":[{1432933860:1622},{1432935660:1458},{1432937461:1388}]},{"name":"Series 2","data":[{1432933860:1622},{1432935660:1458},{1432937461:1388}]}]
What am I doing wrong? Are keys always quoted perhaps?? Any way around this?
http://json.org/
From Objects
An object structure is represented as a pair of curly brackets surrounding zero or more name/value pairs (or members). A name is a string.
and from Strings
A string begins and ends with quotation marks.
So I would say that according to the standard: yes, you should always quote the key. Maby you could try to escape that key in javascript? Store them in a value and remove all non-numeric characters?
Something like:
myJsonKey = myJsonKey.replace(/\D/g,'');

Decode JSON from MySQL

I have JSON string in MySQL database like this
{
"string1": {
"substring1": 1234
},
"string2": {
"substring2": "substring2.1",
"substring3": "substring3.1",
"substring4": {
"substring4.1": 1234,
"substring4.2": 1234,
"substring4.3": 1234
}
}
}
I put those data from MySQL into $string, then I decode it with this function
$json_a = json_decode($string,true);
echo $json_a['string1']['substring1'];
But the result is nothing.
Then I tried to change the $string into
$string = '{"string1":{"substring1":1234},"string2":{"substring2":"substring2.1","substring3":"substring3.1","substring4":{"substring4.1":1234,"substring4.2":1234,"substring4.3":1234}}}';
Next, I use the same function as above and works fine.
Is there any specific things we should do before decode it from mysql?
Thank you
The outer layer of the data you have is not an array, in fact you don't have any arrays in the data at all. Don't use [0] in your PHP.
Access your index with
echo $json_a['string1']['substring1'];

Categories