PHP Merge json files [duplicate] - php

This question already has answers here:
Merging two json in PHP
(4 answers)
Closed 2 years ago.
I have 2 json file each file contain 500 arrays. i need to merge 2 files in 1 file so the result will be 1000 arrays. I have found code from stackoverflow but its not working its just showing me the file 1 data.
<?php
$a = file_get_contents ("cache.json");
$b = file_get_contents ("cache2.json");
$r = [];
foreach(json_decode($a, true) as $key => $array){
$r[$key] = array_merge(json_decode($b, true)[$key],$array);
}
echo count($r);
?>
The json data look like this
$a = '[{"COLUMN_NAME":"ORDER_NO","COLUMN_TITLE":"Order Number"},{"COLUMN_NAME":"CUSTOMER_NO","COLUMN_TITLE":"Customer Number"}]';
$b = '[{"COLUMN_NAME":"ORDER_NO","DEFAULT_VALUE":"1521"},{"COLUMN_NAME":"CUSTOMER_NO","DEFAULT_VALUEE":"C1435"}]';

Try array_merge with json_decode
$r = array_merge(json_decode($a,true), json_decode($b,true));
echo json_encode($r);
Working example : https://3v4l.org/J6iW3

Alternative solution, without decoding:
function concatJsonArrays(...$arrays) {
$result = [];
foreach ($arrays as $array) {
$result[] = substr($array, 1, strlen($array) - 2);
}
return "[".implode(',', $result)."]";
}
// print result aray
echo concatJsonArrays($a, $b);
This solution must be better, if you have big json data or deep objects in json.

You can use array merge but I would suggest first ensuring the JSON code is valid AND the files exist before assuming json_decode will return an array. Otherwise, if you merge NULL or FALSE with an array, you end up with FALSE as the final result.
Imagine the first cache file exists, and the other one doesn't or one of them is broken and contains broken encoded JSON data.
With checks, at least you know you will always get an array with as much of the valid array data as possible or know when to report errors and one which file in one of the stages.
$data = Array();
foreach(Array("cache.json","cache2.json") as $f){
$dc = Array();
if($fc = file_get_contents($f)){
if($dc = json_decode($fc,true)){
$data = empty($data)?$dc:array_merge($data,$dc);
}
}
}
echo json_encode($data);

Related

automatically increment array dimension [duplicate]

This question already has answers here:
Using a string path to set nested array data [duplicate]
(8 answers)
Closed 3 years ago.
I am trying to find a way to create an array of directories. But as we all know directories can have many subDirs and those subDirs can have more subDir and so on and on. The directories length are unknown as it can change.
Say I have a directory as www/webs/apps/pics and another www/webs/test.
The idea would be to have an array such as: (yes the below is json, i just converted it in my php demonstration because i find it easier to read)
{
"www": {
"webs": {
"apps": {
"pics": "Im Here"
}
},
"test": "im Here too"
}
}
There is no relation from the above output to the below code. The below code is here just to give an idea what I need.
$exploedDir = explode("/", $unsortedDir);
foreach ($exploedDir as $dir){
$this->allDirectiroesFound[$dir] = $dir;
}
How can I make $this->allDirectiroesFound has as many dimensions as it is needed without knowing the length of the directory, I cant hard code $this->allDirectiroesFound[][][][][][] it as next time around the array length might be [][][].
You can just reverse each of the path arrays and then go on creating the Keys from the last directory.
$paths = [
'www/webs/apps/pics',
'www/webs/test',
];
$finalArray = [];
foreach($paths as $path){
$revArr = array_reverse(explode("/", $path)); // This is the trick. Start to build from inside out.
$pathArray = [];
foreach($revArr as $key){
$tempBucket = $pathArray;
$pathArray = []; // Create fresh empty array to hold the
$pathArray[$key] = $tempBucket;
}
$finalArray = array_merge_recursive($pathArray, $finalArray); // Recursively Merge the array into the main array
}
echo "<pre>";
print_r(json_encode($finalArray, JSON_PRETTY_PRINT));
echo "</pre>";
DEMO
I guess you would need to use arrays of arrays to solve this.
e.g.
var directories = ["base"];
var subdir1 = ["subdir1"];
var subsubdir1 = ["subsubdir1"];
var subsubdir1 = ["subsubdir2"];
subdir.push(subsubdir1);
subdir.push(subsubdir2);
directories.push(subdir1);
so this forms a base->subdir1->[subsubdir1, subsubdir2] structure. The complication comes in ensuring that every 'push' you perform is an array to allow adjacent siblings to exist for that particular sub-directory. That and keeping track of the directory structure

Input CSV to Array assign keys

This works. It's sort-of a generic csv file importer and key assigner. Looking for feedback how this approach could be made more elegant. I started learning php last week. This forum is fantastic.
<?php
$csvfilename = "sdb.csv";
$filekeys = array('SSID','EquipName','EquipTypeSignalName','elecpropID');
$records = InputCsvFile($csvfilename,$filekeys);
function InputCsvFile($filename,$filekeys){
$array1 = array_map('str_getcsv', file($filename));
foreach($array1 as $element){
$int1 = 0;
unset($array3);
foreach($filekeys as $key){
$array3[$key] = $element[$int1];
$int1++;}
$array2[] = $array3;}
return $array2;}
?>
Using array_map() is clever, but since you have to further process each row, is somewhat unnecessary. I would rewrite InputCsvFile like this:
function InputCsvFile($filename, array $columns) {
$expectedCols = count($columns);
$arr = [];
// NOTE: Confirm the file actually exists before getting its contents
$rows = file($filename);
foreach($rows as $row) {
$row = str_getcsv($row);
if (count($row) == $expectedCols)) {
$arr[] = array_combine($filekeys, $element);
} else {
// Handle the column count mismatch. The test is required because
// otherwise, array_combine will complain loudly.
}
}
return $arr;
}
Alternatively, since you're dealing with files, you could loop on fgetcsv(), rather than using file() + str_getcsv(). Using fgetcsv() will use less memory (since the entire file doesn't have to be read in entirely and be kept in memory through the duration of the iteration), which may or may not be a concern depending on your file sizes.
array_combine() (which incidentally, is one of my favorite functions in PHP) creates a new array given arrays of keys (your list of columns in your $filekeys array) and values (the processed rows from the csv), and is practically tailor-made for turning csv files into more usable arrays.

Removing array index reference when using json_encode()

I have made a small application using jQuery's datepicker. I am setting unavailable dates to it from a JSON file which looks like this:
{ "dates": ["2013-12-11", "2013-12-10", "2013-12-07", "2013-12-04"] }
I would like to check if a date given is already in this list and remove it if so. My current code looks like this:
if (isset($_GET['date'])) //the date given
{
if ($_GET['roomType'] == 2)
{
$myFile = "bookedDates2.json";
$date = $_GET['date'];
if (file_exists($myFile))
{
$arr = json_decode(file_get_contents($myFile), true);
if (!in_array($date, $arr['dates']))
{
$arr['dates'][] = $_GET['date']; //adds the date into the file if it is not there already
}
else
{
foreach ($arr['dates'] as $key => $value)
{
if (in_array($date, $arr['dates']))
{
unset($arr['dates'][$key]);
array_values($arr['dates']);
}
}
}
}
$arr = json_encode($arr);
file_put_contents($myFile, $arr);
}
}
My problem here is that after I encode the array again, it looks like this:
{ "dates": ["1":"2013-12-11", "2":"2013-12-10", "3":"2013-12-07", "4":"2013-12-04"] }
Is there a way to find the date match in the JSON file and remove it, without the keys appearing after the encode?
Use array_values() for your issue:
$arr['dates'] = array_values($arr['dates']);
//..
$arr = json_encode($arr);
Why? Because you're unsetting array's key without re-ordering it. So after this the only way to keep that in JSON will be encode keys too. After applying array_values(), however, you'll get ordered keys (starting from 0) which can be encoded properly without including keys.
You are ignoring the return value of array_values in your existing attempt to reindex the array. Correct is
$arr['dates'] = array_values($arr['dates']);
The reindexing should also be moved outside the foreach loop, there is no point in reindexing multiple times.
In Laravel collections(just in case) you can do
$newArray = $collection->values()->toArray();
or
$jsonEncoded = $collection->values()->toJson();
Just pass second parameter as 'JSON_PRETTY_PRINT' to json_encode() function:
json_encode($arr, JSON_PRETTY_PRINT);
or
json_encode($arr, 128);

PHP JSON encode- Manually assign keys?

I am trying to convert a MySQL query result into JSON within an AJAX request.
My code looks like this at the moment.
$offset = empty($_GET['offset']) ? 0 : $_GET['offset'];
$numimagestodisplay = 3;
$items = array();
$allitems // This is the queryset obtained through a call to a function
foreach ($allitems as $i => &$item)
{
if (($i >= $offset) && (count($items) < $numimagestodisplay))
{
$items[$i] = $item;
}
}
$output = '{"items":'.json_encode($items).'}';
I then want to cycle through the returned results in the javascript calling the above code and need to refer to the array items by their keys (I need to alter some HTML element IDs using these values). However, the JSON is returned in the wrong format.
If I change the line
$items[$i] = $item;
to:
$items[] = $item;
Then I can refer to it by key, however the keys are obviously just 0, 1, 2, whereas I need the key to be the value defined in the loop.
How can I alter the PHP code to return the JSON in the correct format?
Any advice appreciated.
Thanks.
The problem is that arrays in Javascript (and most other languages for that matter) can't have user defined keys. You want your array to be encoded to a JSON object instead of an array (arrays in PHP with user-defined keys are in essence objects). This usually happens automatically, for arrays with non-numeric keys.
In your case, you can use the JSON_FORCE_OBJECT flag:
$output = '{"items":'.json_encode($items,JSON_FORCE_OBJECT).'}';
From the documentation:
Non-associative array output as array: [[1,2,3]]
Non-associative array output as object: {"0":{"0":1,"1":2,"2":3}}

Make 1d Array from 1st member of each value in 2d Array | PHP

How can you do this? My code seen here doesn't work
for($i=0;i<count($cond);$i++){
$cond[$i] = $cond[$i][0];
}
It can be as simple as this:
$array = array_map('reset', $array);
There could be problems if the source array isn't numerically index. Try this instead:
$destinationArray = array();
for ($sourceArray as $key=>$value) {
$destinationArray[] = $value[0]; //you may want to use a different index than '0'
}
// Make sure you have your first array initialised here!
$array2 = array();
foreach ($array AS $item)
{
$array2[] = $item[0];
}
Assuming you want to have the same variable name afterwards, you can re-assign the new array back to the old one.
$array = $array2;
unset($array2); // Not needed, but helps with keeping memory down
Also, you might be able to, dependant on what is in the array, do something like.
$array = array_merge(array_values($array));
As previously stated, your code will not work properly in various situation.
Try to initialize your array with this values:
$cond = array(5=>array('4','3'),9=>array('3','4'));
A solution, to me better readable also is the following code:
//explain what to do to every single line of the 2d array
function reduceRowToFirstItem($x) { return $x[0]; }
// apply the trasnformation to the array
$a=array_map('reduceRowTofirstItem',$cond);
You can read the reference for array map for a thorough explanation.
You can opt also for a slight variation using array_walk (it operate on the array "in place"). Note that the function doesn't return a value and that his parameter is passed by reference.
function reduceToFirstItem(&$x) { $x=$x[0]; }
array_walk($cond, 'reduceToFirstItem');
That should work. Why does it not work? what error message do you get?
This is the code I would use:
$inArr;//This is the 2D array
$outArr = array();
for($i=0;$i<count($inArr);$i++){
$outArr[$i] = $inArr[$i][0];
}

Categories