I am verifying certain codes that work well and I don't know what else to optimize in them or what other tests to do: in this case it is a php script that takes the data of the $_POST
variable analyzes them and converts them into an array, this is since in some cases the post field may contain a JSon
string.
I leave a functional example where I have manually set the $_POST
variable to do the Demonstration:
https://wtools.io/php-sandbox/bqsT
Original Code example:
<?php
#Example Array
$_POST = array(
"valor1" => 1200,
"valor2" => "texto",
"valor3" => true,
"valor4" => '{"seclvl_text":"datp","seclvl_boolean":"false"}',
);
#Validate Function for Json
function ValidateJson($Var) {
if (!is_array($Var)) {
return ((json_decode($Var) != null) AND (is_object(json_decode($Var)) OR is_array(json_decode($Var)))) ? true : false;
} else {
return false;
}
}
#Parse Function
function buildVirtualData($data) {
if (is_array($data)) {
$result = [];
foreach ($data as $key1 => $val1) {
$valJson = ValidateJson($val1);
if ($valJson) {
$jsonObj = json_decode($val1, true);
$result[$key1] = buildVirtualData($jsonObj);
} elseif ($valJson == false && is_array($val1)) {
foreach ($val1 as $key2 => $val2) {
$result[$key1][$key2] = buildVirtualData($val2);
}
} else {
if ($val1 === 'true') {
$val1 = true;
} else if ($val1 === 'false') {
$val1 = false;
}
$result[$key1] = $val1;
}
}
return $result;
} else {
if (ValidateJson($data)) {
$jsonObj = json_decode($data, true);
return buildVirtualData($jsonObj);
} else {
return $data;
}
}
}
# call to Function:
$data = buildVirtualData($_POST);
echo '<pre>';
echo var_dump($data);
echo '</pre>';
this parse have the feature that convert any text true or false to Boolean.
2 Answers 2
I think you're are definitely on the right track here. I spent a good deal of time trying to refactor, here's what I came up with
#Validate Function for Json
function jsonDecodeAndValidate($var, $assoc = false) {
if(!is_string($var))
return false;
if(!$decoded = json_decode($var, $assoc))
return false;
if(!is_object($decoded) && !is_array($decoded))
return false;
return $decoded;
}
#Parse Function
function buildVirtualData($data) {
if (is_array($data) || is_object($data)) {
foreach ($data as $key1 => $val1) {
if(is_array($val1)){
foreach ($val1 as $key2 => $val2) {
$result[$key1][$key2] = buildVirtualData($val2);
}
}
else if($decoded = jsonDecodeAndValidate($val1)){
$result[$key1] = buildVirtualData($decoded);
} else {
if(in_array($val1, ['true', 'false']))
$val1 = filter_var($val1, FILTER_VALIDATE_BOOLEAN);
$result[$key1] = $val1;
}
}
return $result;
} else {
if ($decoded = jsonDecodeAndValidate($data, true)) {
return buildVirtualData($decoded);
} else {
return $data;
}
}
}
At the very least this will save you some calls to json_decode
as the decoding is done once per iteration.
EDIT: I took another stab at it. I think you can boil it down to this.
#decodeand validate
function jsonDecodeAndValidate($var) {
if(!is_string($var))
return $var;
if(!$decoded = json_decode($var, true))
return $var;
if(!is_array($decoded))
return $var;
return $decoded;
}
#Parse Function
function buildVirtualData($data, &$build) {
$data = jsonDecodeAndValidate($data);
if(is_array($data) || is_object($data)){
foreach($data as $key => $value){
buildVirtualData($value, $build[$key]);
}
} else {
if ($data === 'true')
$data = true;
if ($data === 'false')
$data = false;
$build = $data;
}
}
# call to Function:
$build = [];
buildVirtualData($_POST, $build);
echo '<pre>';
echo json_encode($build, JSON_PRETTY_PRINT);
echo '</pre>';
You just have to declare your array outside of the function.
-
\$\begingroup\$ this trown error: filter_var($data, FILTER_VALIDATE_BOOLEAN); \$\endgroup\$Minos Framework– Minos Framework2019年10月30日 21:08:28 +00:00Commented Oct 30, 2019 at 21:08
-
\$\begingroup\$ is and error of the website sandbox test... sorry \$\endgroup\$Minos Framework– Minos Framework2019年10月30日 21:13:06 +00:00Commented Oct 30, 2019 at 21:13
-
1\$\begingroup\$ I love it when I see this:
&$build
optimizing memory usage with pointers. \$\endgroup\$Minos Framework– Minos Framework2019年10月30日 21:18:03 +00:00Commented Oct 30, 2019 at 21:18 -
\$\begingroup\$ I changed that part back to what it was. Seems you need a module installed to use
filter_var
\$\endgroup\$Rager– Rager2019年10月30日 21:42:49 +00:00Commented Oct 30, 2019 at 21:42
I don't think your JSON validation function is very useful because it does more or less what does the json_decode
function itself, except that it tests if the result is an array or an object (that is useless too, since buildVirtualData
always uses json_decode
with the second parameter set to true
and since the $_POST
variable can't contain an object but only strings and arrays.).
Always use a strict comparison with null when you want to check the return of json_decode
for validity. As a counter-example, elements like an empty string, 0 or false
that are valid JSON themselves, return true
in this non-strict comparison: var_dump(json_decode('""') == null);
Manualy replacing the strings "true" or "false" with a boolean isn't needed since json_decode
does that automatically.
You can rewrite your function like that:
function buildVirtualData($var) {
if ( is_string($var) ) {
$json = json_decode($var, true);
if ( $json !== null )
$var = $json;
}
if ( is_array($var) )
return array_map('buildVirtualData', $var);
return $var;
}
-
\$\begingroup\$ This wouldn't work if a php object were passed. Or rather, it wouldn't parse it into an array. \$\endgroup\$Rager– Rager2019年11月01日 12:47:08 +00:00Commented Nov 1, 2019 at 12:47
-
1\$\begingroup\$ @Rager: a POST variable doesn't contain php object. \$\endgroup\$Casimir et Hippolyte– Casimir et Hippolyte2019年11月01日 15:42:45 +00:00Commented Nov 1, 2019 at 15:42
-
\$\begingroup\$ $_POST = json_decode( <<<JSON { "valor1" : 1200, "valor2: : "texto", "valor3" : true, "valor4" : "{\"seclvl_text\":\"datp\",\"seclvl_boolean\":\"false\"}" } JSON ); \$\endgroup\$Rager– Rager2019年11月01日 17:50:03 +00:00Commented Nov 1, 2019 at 17:50
-
\$\begingroup\$ @Rager: are you serious? \$\endgroup\$Casimir et Hippolyte– Casimir et Hippolyte2019年11月01日 17:53:00 +00:00Commented Nov 1, 2019 at 17:53
-
\$\begingroup\$ I guess you're right. $_POST cannot be object. \$\endgroup\$Rager– Rager2019年11月01日 18:00:31 +00:00Commented Nov 1, 2019 at 18:00