In PHP, how to get a JSON value from a variable path ?
Here is a sample json and a function with 2 params: a json variable, and path split into keys.
$myjson = json_decode('{
"myKey1": {
"myKey2": {
"myKey3": {
"myKey4": "myfinalvalue"
}
}
}
}');
function getJSONValue($myjson, $pathkey) {
// split path keys by ";"
$myjson-> ?? $pathkey ??
}
echo getJSONValue($myjson, "myKey1;myKey2;myKey3;myKey4");
// Should display "myfinalvalue"
the static equivalent would be to do:
$myjson->myKey1->myKey2->myKey3->myKey4;
I tried:
$myjson->$pathkey
but unfortunately, it doesn't work...
Actually, your question has nothing to do with JSON. This is how you can get a value from a nested object:
function getValue($obj, $path) {
foreach(explode(';', $path) as $key) {
$obj = $obj->$key;
}
return $obj;
}
As for the JSON part, your example is not a valid JSON. It should be like this:
$myjson = json_decode('{
"myKey1": {
"myKey2": {
"myKey3": {
"myKey4": "myfinalvalue"
}
}
}
}');
Also, php objects are case-sensitive, if you have myKey in the object, it should be myKey (and not mykey) in the path string.
function getJSONValue($myjson, array $pathkey) {
foreach($pathkey as $val){
$myjson = $myjson->{$val};
}
return $myjson;
}
$myjson = json_decode('{"myKey1": {"myKey2": {"myKey3": {"myKey4": "myfinalvalue"}}}}');
echo getJSONValue($myjson, ["myKey1","myKey2","myKey3","myKey4"]);
live example: http://codepad.viper-7.com/1G78Fi
Something like this:
function getJSONValue() {
$args = func_get_args();
$json = array_shift($args);
$key = array_shift($args);
$value = $json->$key;
if(is_object($value)) {
array_unshift($args, $value);
return call_user_func_array('getJSONValue', $args);
}
return $value;
}
No error checking.
Seems like you are mixing PHP and JS. check this out to see how to create a Json string, then getting an onject out of it, and accessing keys:
$myjson = json_encode(array(
'myKey1' => array(
'mykey2' => array(
'mykey3' => array(
'myKey4' => "myfinalvalue"
)
)
)
));
$obj = json_decode($string);
echo $obj->myKey1->mykey2->mykey3->myKey4
// "myfinalvalue"
or pasting the json directly:
$obj = json_decode(
'{
myKey1: {
mykey2: {
mykey3: {
myKey4: "myfinalvalue"
}
}
}
}');
echo $obj->myKey1->mykey2->mykey3->myKey4
// "myfinalvalue"
To understand it betterm, read about JSON_DECODE
Related
$session_activity_category = array();
foreach($search_venue as $venue_b) {
$session_activity_category[] = $this->users_model->search_categories_by_session($venue_b->activity_venue_id);
}
return $this->output
->set_content_type('application/json')
->set_status_header(200)
->set_output(json_encode(array('activity_category'=>$session_activity_category,'activity'=>$session_activity,'activity_session'=>$search_session,'activity_venue'=>$search_venue),JSON_UNESCAPED_SLASHES)
);
I want to remove the arrays given in the arrow lines
Convert the JSON to the array. Then just create a new array with the same key active category (in my example, something):
<?php
$json = '
{"something": [[
{
"blah": "blah"
},
{
"blah": "blah"
}
]]}
';
$array = json_decode($json, true);
$array = [
"something" => $array['something'][0],
];
echo json_encode($array);
Which will output:
{"something":[{"blah":"blah"},{"blah":"blah"}]}
Seems that $this->users_model->search_categories_by_session($venue_b->activity_venue_id) returns array of objects. You should parse this objects to the $session_activity_category array each iteration of search_categories_by_session function call.
$session_activity_category = array();
array_walk($search_venue, function($venue_b) use (&$session_activity_category) {
$categories = $this->users_model->search_categories_by_session($venue_b->activity_venue_id);
foreach ($categories as $category) {
$session_activity_category[] = $category;
}
});
Is there a way to retreive a key from JSON string with out going in to foreach loop?
$json ="{\"error\":{\"code\":301}}";
if (empty($json)) {
die('empty string');
} else {
$obj = json_decode($json);
foreach ($obj as $key => $object) {
echo $key;
}
}
What I need is to detect where the string contains error or not, so I can create error handling.
Thanks in advance
You can use property_exists() method:
$json ="{\"error\":{\"code\":301}}";
if (empty($json)) {
die('empty string');
} else {
$obj = json_decode($json);
var_dump(property_exists($obj, 'error'));
}
I have an object with data stored at multiple levels ( a JSON-decoded document ) like this:
$db = (object) array(
'simple_property' => 'value',
'complex_property' => (object) array(
'key' => 'value',
'nested' => (object) array(
'key' => 'value'
)
)
);
I want to be able to access and update data at any depth via reference. Example:
$db->{ $key } = $new_value
If $key is equal to 'simple_property', that works. But if $key is equal to 'complex_property->nested->key', it doesn't. Is there a way to accomplish what I want to, or am I looking at it incorrectly?
I don't think you can get it to work that way. You'll have to create a function (or class method) to do something like that. As an example:
function getRecursiveProperty($object, $path)
{
$array = explode('->', $path);
if (empty($array))
{
return NULL;
}
foreach ($array as $property)
{
if (!isset($object->$property))
{
return NULL;
}
if (!is_object($object->$property))
{
return $object->$property;
}
$object = $object->$property;
}
return $object->$property;
}
function setRecursiveProperty($object, $path, $value)
{
foreach (explode('->', $path) as $property)
{
if (!isset($object->$property))
{
return FALSE;
}
if (!is_object($object->$property))
{
$object->$property = $value;
return TRUE;
}
$object = $object->$property;
}
return FALSE;
}
$key = 'complex_property->nested->key';
echo getRecursiveProperty($db, $key); // value
setRecursiveProperty($db, $key, 'new_value');
echo getRecursiveProperty($db, $key); // new_value
Why you don't use $db = json_decode($json, true); instead of $db = json_decode($json);?
In this way you return an associative array instead of an object and you will not have these problems anymore.
json_decode ( string $json , bool $assoc)
json
The json string being decoded.
This function only works with UTF-8 encoded strings.
assoc
When TRUE, returned objects will be converted into
associative arrays.
More info: http://php.net/manual/en/function.json-decode.php
What I need is,
but what i got is,
How can I remove "#attributes" from the result.
The below code works for me:
// Cleans up ugly JSON data by removing #attributes tag
function cleanup_json ($ugly_json) {
if (is_object($ugly_json)) {
$nice_json = new stdClass();
foreach ($ugly_json as $attr => $value) {
if ($attr == '#attributes') {
foreach ($value as $xattr => $xvalue) {
$nice_json->$xattr = $xvalue;
}
} else {
$nice_json->$attr = cleanup_json($value);
}
}
return $nice_json;
} else if (is_array($ugly_json)) {
$nice_json = array();
foreach ($ugly_json as $n => $e) {
$nice_json[$n] = cleanup_json($e);
}
return $nice_json;
} else {
return $ugly_json;
}
}
// Convert XML to JSON
function convert_to_json ($xml_string) {
$xml = simplexml_load_string($xml_string);
$ugly_json = json_decode(json_encode($xml));
$nice_json = cleanup_json($ugly_json);
return json_encode($nice_json, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}
Try this. It may work for you.
$xml = simplexml_load_string($string);
$json = json_encode($xml, true);
$json = '[
{
"class1":
{
"function1":"return \"$a<b>$b</b>!\";"
}
},
{
"class2":
{
"function2":"return $b;",
"function3":"return $c;"
}
}
]';
$decoded_classes = json_decode($json,true);
foreach($decoded_classes as $class)
{
$class_name = key($class);
if (is_array($class[$class_name]))
{
foreach($class[$class_name] as $function)
{
$function_name = key($class[$class_name]);
$stack[$class_name][$function_name] = create_function($arr,$function);
}
}
else
{
foreach($class as $function)
{
$c_name = key($class);
$stack[$c_name] = create_function($arr,$function);
}
}
}
return $stack;
I need that this code will execute the same result but with only one foreach. How can i do that?
Translating the JSON to... let's say "PHPON", you get:
$decoded_classes = Array(
Array(
"class1"=>Array(
"function1"=>'return "$a<b>$b</b>!";'
)
)
Array(
"class2"=>Array(
"function2"=>'return $b;',
"function3"=>'return $c;'
)
)
);
As you can see, your structure isn't exactly the most efficient. You basically have one too many levels.
Restructure the JSON like this:
{
"class1": {
"function1":"return \"$a<b>$b</b>!\";"
},
"class2": {
"function2":"return $b;",
"function3":"return $c;"
}
}
In this way, the "PHPON" is:
$decoded_classes = Array(
"class1"=>Array(
"function1"=>'return "$a<b>$b</b>!";'
)
"class2"=>Array(
"function2"=>'return $b;',
"function3"=>'return $c;'
)
);
Now you don't even need to loop at all. Accessing $decoded_classes['class1']['function1'] will give you that code. The only thing you have to do is convert those strings into callable functions, like so:
array_walk_recursive($decoded_classes,function(&$f) {$f = create_function($arr,$f);});
I can't help but notice you didn't define $arr anywhere in your code. You'll have to specify $arr correctly for this to work.