I have json string that I have to edit and then transform back to json. But unfortunately I can't really restore the json structure.
The structure of the original json string ($json):
"[{"Language":{"0":"EN"},"Text":{"0":"xxx"},"ContentType":{"0":"PlainText"}},
{"Language":{"0":"DE"},"Text":{"0":"xxx"},"ContentType":{"0":"PlainText"}},
{"Language":{"0":"FR"},"Text":{"0":"xxx"},"ContentType":{"0":"PlainText"}}]"
The structure I get after my edits ($newJson):
"{"0":{"Language":{"0":"EN"},"Text":{"0":"yyy"},"ContentType":{"0":"PlainText"}},
"1":{"Language":{"0":"DE"},"Text":{"0":"yyy"},"ContentType":{"0":"PlainText"}},
"2":{"Language":{"0":"FR"},"Text":{"0":"yyy"},"ContentType":{"0":"PlainText"}}}"
Here is what I do with my edits:
$jsonArray = object_to_array(json_decode($json));
$editedJsonArray = someLoopStuff($jsonArray);
$newJson = json_encode(array_to_object(($editedJsonArray)));
function object_to_array($obj) {
if(is_object($obj)) $obj = (array) $obj;
if(is_array($obj)) {
$new = array();
foreach($obj as $key => $val) {
$new[$key] = $this->object_to_array($val);
}
}
else $new = $obj;
return $new;
}
function array_to_object($a) {
if (is_array($a) ) {
foreach($a as $k => $v) {
$a[$k] = $this->array_to_object($v);
}
return (object) $a;
}
return $a;
}
Do you have an idea how I could get the same structure as the original json?
Use arrays instead of objects. Pass true to json_decode() as second argument and then do your stuff on arrays.
$jsonArray = json_decode($json, true);
Then just make your operation in loop on $jsonArray and simply use json_encode() without any additional work.
To achieve exactly same output as you have on input you need to cast subarrays on objects:
$jsonArray = json_decode('[{"Language":{"0":"EN"},"Text":{"0":"xxx"},"ContentType":{"0":"PlainText"}},{"Language":{"0":"DE"},"Text":{"0":"xxx"},"ContentType":{"0":"PlainText"}},{"Language":{"0":"FR"},"Text":{"0":"xxx"},"ContentType":{"0":"PlainText"}}]', true);
foreach ($jsonArray as &$item) {
foreach ($item as &$val) {
$val = (object) $val;
}
unset($val);
}
unset($item);
var_dump(json_encode($jsonArray));
Output:
string(226) "[{"Language":{"0":"EN"},"Text":{"0":"xxx"},"ContentType":{"0":"PlainText"}},{"Language":{"0":"DE"},"Text":{"0":"xxx"},"ContentType":{"0":"PlainText"}},{"Language":{"0":"FR"},"Text":{"0":"xxx"},"ContentType":{"0":"PlainText"}}]"
What if you would try to avoid using functions object_to_array and array_to_object. In the encoding part it is not necessary, because json_encode can handle objects or arrays. In the first part json_decode can be called with second optional parameter set to true to produce array instead of object. See PHP manual.
Related
I have a MYSQL query that fetches an array of dictionaries or results which are returned via JSON in an api. In some cases, I would like to change the name of the dictionary keys in the results array.
For example, in the following case:
$var = '[{"player":"Tiger Woods"},{"player":"Gary Player"}]';
I would like to change it to:
$var = '[{"golfer":"Tiger Woods"},{"golfer":"Gary Player"}]'
It is not practical in this case to change the mysql query so I'd just like to replace the word "player" with the word "golfer" for the keys without disturbing the values.
In the above example, I would not want to change Gary Player's name so just using str_replace does not seem like it would work.
Is there a way to change all of the keys from "player" to "golfer" without changing any of the values?
Here is the snippet you can use
$var = '[{"player":"Tiger Woods"},{"player":"Gary Player"}]';
// json decode the json string
$temp = json_decode($var, true);
$temp = array_map(function($item){
// combining key and values
return array_combine(['golfer'], $item);
}, $temp);
print_r($temp);
// or echo json_encode($temp);
Demo.
Some argue that foreach is fastest,
foreach($temp as $k => &$v){
$v = array_combine(['golfer'], $v);
}
print_r($temp);
Demo.
Little hardcoded if more than one keys in single array,
foreach ($temp as $k => &$v){
$v['golfer'] = $v['player'];
unset($v['player']);
}
print_r($temp);
Demo.
Using recursion
function custom($arr, $newKey, $oldKey)
{
// if the value is not an array, then you have reached the deepest
// point of the branch, so return the value
if (!is_array($arr)) {
return $arr;
}
$result = []; // empty array to hold copy of subject
foreach ($arr as $key => $value) {
// replace the key with the new key only if it is the old key
$key = ($key === $oldKey) ? $newKey : $key;
// add the value with the recursive call
$result[$key] = custom($value, $newKey, $oldKey);
}
return $result;
}
$var = '[{"player":"Tiger Woods"},{"player":"Gary Player"}]';
$temp = json_decode($var, true);
$temp = replaceKey($temp, 'golfer', 'player');
print_r($temp);
Demo & source.
Using json way,
function json_change_key($arr, $oldkey, $newkey) {
$json = str_replace('"'.$oldkey.'":', '"'.$newkey.'":', json_encode($arr));
return json_decode($json, true);
}
$temp = json_change_key($temp, 'player', 'golfer');
print_r($temp);
Demo
If you want multiple key replace, here is the trick,
$var = '[{"player":"Tiger Woods", "wins":"10","losses":"3"},{"player":"Gary Player","wins":"7", "losses":6}]';
$temp = json_decode($var, true);
function recursive_change_key($arr, $set)
{
if (is_array($arr) && is_array($set)) {
$newArr = [];
foreach ($arr as $k => $v) {
$key = array_key_exists($k, $set) ? $set[$k] : $k;
$newArr[$key] = is_array($v) ? recursive_change_key($v, $set) : $v;
}
return $newArr;
}
return $arr;
}
$set = [
"player" => "golfers",
"wins" => "victories",
"losses" => "defeats"
];
$temp = recursive_change_key($temp, $set);
print_r($temp);
Demo.
$a = '[{"player":"Tiger Woods"},{"player":"Gary Player"}]';
$array = json_decode($a, true);
foreach($array as $key=>$value){
if(array_keys($value)[0] === "player"){
$array[$key] = ["golfer" => array_values($value)[0]];
};
}
echo json_encode($array);
you can write the value of the key to a new key and then delete the old.
renaming a key called "a" to "b", while keeping the value.
var json = {
"a" : "one"
}
json["b"] = json["a"];
delete json["a"];
for your example, just use this with a loop.
source: https://sciter.com/forums/topic/how-to-rename-the-key-of-json/
Can any one help me to read this type of json response.
{"\u0000*\u0000_translate":
{
"app_text_newcomer":"Newcomer",
"app_text_senior":"Senior",
"app_text_mostsenior":"Most Senior",
"app_text_results":"Result",
"app_text_result":"Result",
"app_text_agenda":"Agenda",
"app_text_dbvg":"Dbvg"
},
"0":{}
}
how can i get this value \u0000*\u0000_translate
Looks like JSON, so use json_decode to get a PHP object or associative array.
Edit: Having just tried it, I see your problem. json_decode() can't handle nulls in the data, so you should file a bug about that.
Workaround: Preprocess \u0000 to some sentinel value you can later replace for a real null, such as this:
$json = '{"\u0000*\u0000_translate": { "app_text_newcomer":"Newcomer", "app_text_senior":"Senior", "app_text_mostsenior":"Most Senior", "app_text_results":"Result", "app_text_result":"Result", "app_text_agenda":"Agenda", "app_text_dbvg":"Dbvg"}, "0":{}}';
$json = str_replace('\u0000', 'XNULLX', $json);
$arr = json_decode($json, true);
foreach ($arr as $k => $v) {
if (strpos($k, 'XNULLX') !== false) {
unset($arr[$k]);
$k = str_replace('XNULLX', "\0", $k);
$arr[$k] = $v;
}
}
echo var_export($arr, true);
I am newbee in php and trying to get json in array and wanna change key in that json below is my code :
$json = json_decode(file_get_contents('all_json_files/jobs.json'), true);
foreach ($json as $key=>$row){
foreach ( $row as $key=>$row){
foreach ( $row as $key=>$row){
foreach ($row as $key=>$row){
if(strcmp($key,"security_block")==0)
{
foreach ($row as $k=>$r){
if(strcmp($k,"job_payload_hash")==0)
{
$row[$k]['job_payload_hash']=$base64String;
print_r($row);
}
}
}
}
}
}
}
print_r($json);
Issue is print_r($row); is updating properly but print_r($json); does not print the updated string .
If the key could appear anywhere, the answer is pretty simple:
function update_hash(&$item, $key, $base64String)
{
if ($key == "job_payload_hash") {
$item = $base64String;
}
}
array_walk_recursive($json, 'update_hash', 'something');
Update
The structure is something different that previously assumed; while the above will work, probably the below is a more direct approach:
foreach (array_keys($json['jobs']) as $jobId) {
$json['jobs'][$jobId]['job']['security_block']['job_payload_hash'] = 'something';
}
You use $key & $row variable in multiple time. for this reason, value of $key is changed each time, so parent loop does not work..
You can use recursive function lik answer of #Ja͢ck .
this is because you have to save not in variables you defined after => in a foreach.
You have to store this in format:
$json[0][0] ... = $base64String;
OR
You have to add a new array like $result = array() before you write the foreach and then store it in $result.
Decode the JSON string using json_decode(), edit your resulting array, then use json_encode(); to return the array to a JSON encoded string.
Also, use array_key_exists() rather than comparing array key strings.
$array = json_decode($json);
if(array_key_exists("job_payload_hash", $array){
$array["job_payload_hash"] = base64encode($var);
}
$json = json_encode($array);
I got stuck somehow on the following problem:
What I want to achieve is to merge the following arrays based on key :
{"Entities":{"submenu_id":"Parents","submenu_label":"parents"}}
{"Entities":{"submenu_id":"Insurers","submenu_label":"insurers"}}
{"Users":{"submenu_id":"New roles","submenu_label":"newrole"}}
{"Users":{"submenu_id":"User - roles","submenu_label":"user_roles"}}
{"Users":{"submenu_id":"Roles - permissions","submenu_label":"roles_permissions"}}
{"Accounting":{"submenu_id":"Input accounting data","submenu_label":"new_accounting"}}
Which needs to output like this:
[{"item_header":"Entities"},
{"list_items" :
[{"submenu_id":"Parents","submenu_label":"parents"},
{"submenu_id":"Insurers","submenu_label":"insurers"}]
}]
[{"item_header":"Users"},
{"list_items" :
[{"submenu_id":"New roles","submenu_label":"newrole"}
{"submenu_id":"User - roles","submenu_label":"user_roles"}
{"submenu_id":"Roles - permissions","submenu_label":"roles_permissions"}]
}]
[{"item_header":"Accounting"},
{"list_items" :
[{"submenu_id":"Input accounting data","submenu_label":"new_accounting"}]
}]
I have been trying all kinds of things for the last two hours, but each attempt returned a different format as the one required and thus failed miserably. Somehow, I couldn't figure it out.
Do you have a construction in mind to get this job done?
I would be very interested to hear your approach on the matter.
Thanks.
$input = array(
'{"Entities":{"submenu_id":"Parents","submenu_label":"parents"}}',
'{"Entities":{"submenu_id":"Insurers","submenu_label":"insurers"}}',
'{"Users":{"submenu_id":"New roles","submenu_label":"newrole"}}',
'{"Users":{"submenu_id":"User - roles","submenu_label":"user_roles"}}',
'{"Users":{"submenu_id":"Roles - permissions","submenu_label":"roles_permissions"}}',
'{"Accounting":{"submenu_id":"Input accounting data","submenu_label":"new_accounting"}}',
);
$input = array_map(function ($e) { return json_decode($e, true); }, $input);
$result = array();
$indexMap = array();
foreach ($input as $index => $values) {
foreach ($values as $k => $value) {
$index = isset($indexMap[$k]) ? $indexMap[$k] : $index;
if (!isset($result[$index]['item_header'])) {
$result[$index]['item_header'] = $k;
$indexMap[$k] = $index;
}
$result[$index]['list_items'][] = $value;
}
}
echo json_encode($result);
Here you are!
In this case, first I added all arrays into one array for processing.
I thought they are in same array first, but now I realize they aren't.
Just make an empty $array=[] then and then add them all in $array[]=$a1, $array[]=$a2, etc...
$array = '[{"Entities":{"submenu_id":"Parents","submenu_label":"parents"}},
{"Entities":{"submenu_id":"Insurers","submenu_label":"insurers"}},
{"Users":{"submenu_id":"New roles","submenu_label":"newrole"}},
{"Users":{"submenu_id":"User - roles","submenu_label":"user_roles"}},
{"Users":{"submenu_id":"Roles - permissions","submenu_label":"roles_permissions"}},
{"Accounting":{"submenu_id":"Input accounting data","submenu_label":"new_accounting"}}]';
$array = json_decode($array, true);
$intermediate = []; // 1st step
foreach($array as $a)
{
$keys = array_keys($a);
$key = $keys[0]; // say, "Entities" or "Users"
$intermediate[$key] []= $a[$key];
}
$result = []; // 2nd step
foreach($intermediate as $key=>$a)
{
$entry = ["item_header" => $key, "list_items" => [] ];
foreach($a as $item) $entry["list_items"] []= $item;
$result []= $entry;
}
print_r($result);
I would prefer an OO approach for that.
First an object for the list_item:
{"submenu_id":"Parents","submenu_label":"parents"}
Second an object for the item_header:
{"item_header":"Entities", "list_items" : <array of list_item> }
Last an object or an array for all:
{ "Menus: <array of item_header> }
And the according getter/setter etc.
The following code will give you the requisite array over which you can iterate to get the desired output.
$final_array = array();
foreach($array as $value) { //assuming that the original arrays are stored inside another array. You can replace the iterator over the array to an iterator over input from file
$key = /*Extract the key from the string ($value)*/
$existing_array_for_key = $final_array[$key];
if(!array_key_exists ($key , $final_array)) {
$existing_array_for_key = array();
}
$existing_array_for_key[count($existing_array_for_key)+1] = /*Extract value from the String ($value)*/
$final_array[$key] = $existing_array_for_key;
}
I need to combine two different data types, an array and an array object.
I then need to display them on a page in order of a certain attribute (date).
The markup for access is similar to the following:
foreach($array as $item){
$item['date'];
}
and
foreach($object as $item){
$item->post->date
}
is array_merge what I need, or something different?
Not that if possible I'd like to do this on the fly, as data will be changing rapidly and there is no need for storage.
Thanks!
Here's how I would do it:
// array we will use for sorting
$finalArray = array();
// add the array's using the date as the key
foreach($array as $item){
$key = $item['date']; // use date here, example $key = date('l \t\h\e jS',$item['date']);
$finalArray[$key] = $item;
}
// add the objects's using the date as the key
foreach($object as $item){
$finalArray[$item->post->date] = $item;
}
//now sort by keys as Xeoncross noted
ksort($finalArray);
foreach($finalArray as $date=>$objOrArray){
if(is_array($objOrArray)){
//do your array printing here
} else {
//do your object printing here
}
}
Ofcourse we can turn the object into an array with get_object_vars, and use whatever sorting function on the final array, the important part is that we want to sort by date and that's why we need it to be our key.
Hope that helped.
foreach($array as $item){
$array_new[] = $item['date'];
}
foreach($object as $item){
$array_new[] = $item->post->date;
}
sort($array_new);
$dates = array();
foreach ($array as $item) {
$dates[] = $item['date'];
}
foreach ($object as $item) {
$dates[] = $item->post->date;
}
sort($dates);
foreach ($dates as $date) {
echo $date;
}
You could try this if you need multiple values from the objects (not just date) and you don't mind duplicates being erased.
// $array is already defined right?
$object = json_decode(json_encode($object), TRUE);
$data = array_merge($array, $object);
print_r($data); // now test it
http://us2.php.net/array_merge
http://us3.php.net/json_decode (note the second TRUE param)
Edit
Based on Perfection's answer, (and re-reading the question) I would do this:
$finalArray = array();
foreach($array as $item)
{
$finalArray[$item['date']] = $item;
}
foreach($object as $item)
{
$finalArray[$item->post->date] = json_decode(json_encode($item), TRUE);
}
ksort($finalArray);
foreach($finalArray as $date => $item)
{
// Everything is an array now
}