json_encode is adding extra square brackets - PHP - php

json_encode is adding extra square bracket when I write code in to the json file using php.
METHOD to create & write JSON file.
function appendData($data){
$filename='data.json';
// read the file if present
$handle = #fopen($filename, 'r+');
// create the file if needed
if ($handle === null)
{
// $handle = fopen($filename, 'w+');
$handle = fopen($filename, 'w') or die("Can't create file");
}
if ($handle)
{
// seek to the end
fseek($handle, 0, SEEK_END);
// are we at the end of is the file empty
if (ftell($handle) > 0)
{
// move back a byte
fseek($handle, -1, SEEK_END);
// add the trailing comma
fwrite($handle, ',', 1);
// add the new json string
fwrite($handle, json_encode($data,JSON_UNESCAPED_SLASHES) . ']');
}
else
{
// write the first event inside an array
fwrite($handle, json_encode(array($data),JSON_UNESCAPED_SLASHES));
}
// close the handle on the file
fclose($handle);
}
}
Method call with data array argument
$file= appendData($data);
Data
$data= array(
'name' => "abc",
'image_url' => "cdf",
);
The JSON Output comes like
[[{"name":"Apple iPhone 6S\u00a0with FaceTime\u00a0- 32GB, 4G LTE, Gold","image_url":"https://m.media-amazon.com/images/I/51jV7zsrOtL._AC_UL436_.jpg"}]]
Problem: There are extra square brackets appending in json output, that seems fine becuase of using json_encode(array($data)) .
But it doesn't parse on front end using javascript or jquery.
Question: how to parse this double square JSON data using jquery or how to append data properly in json file using php?

I see no problem with your output. You are adding an unnecessary layer of array by json_encode(array($data)) but you just have to factor that into your JS when you try to access the values. You can access it as a 2-d array of objects as in this snippet:
let json = '[[{"name":"Apple iPhone 6S\u00a0with FaceTime\u00a0- 32GB, 4G LTE, Gold","image_url":"https://m.media-amazon.com/images/I/51jV7zsrOtL._AC_UL436_.jpg"}]]';
let v = JSON.parse(json);
console.log(v[0][0].name);
console.log(v[0][0].image_url);

Related

Best way to read a large file in php [duplicate]

This question already has answers here:
Reading very large files in PHP
(8 answers)
Closed 1 year ago.
I have a file with around 100 records for now.
The file has users in json format per line.
Eg
{"user_id" : 1,"user_name": "Alex"}
{"user_id" : 2,"user_name": "Bob"}
{"user_id" : 3,"user_name": "Mark"}
Note : This is a just very simple example, I have more complex json values per line in the file.
I am reading the file line by line and store that in an array which obviously will be big if there are a lot of items in the file.
public function read(string $file) : array
{
//Open the file in "reading only" mode.
$fileHandle = fopen($file, "r");
//If we failed to get a file handle, throw an Exception.
if ($fileHandle === false) {
throw new Exception('Could not get file handle for: ' . $file);
}
$lines = [];
//While we haven't reach the end of the file.
while (!feof($fileHandle)) {
//Read the current line in.
$lines[] = json_decode(fgets($fileHandle));
}
//Finally, close the file handle.
fclose($fileHandle);
return $lines;
}
Next, Ill process this array and only take the parameters I need (some parameters might be further processed) and then Ill export this array to csv.
public function processInput($users){
$data = [];
foreach ($users as $key => $user)
{
$data[$key]['user_id'] = $user->user_id;
$data[$key]['user_name'] = strtoupper($user->user_name);
}
// Call export to csv $data.
}
What should be the best way to read the file (incase we have a big file)?
I know file_get_contents is not optimized way and instead fgets is a better approach.
Is there a much better way considering big file read and then put it to csv.
You need to modify your reader to make it more "lazy" in some sense. For example consider this:
public function read(string $file, callable $rowProcessor) : void
{
//Open the file in "reading only" mode.
$fileHandle = fopen($file, "r");
//If we failed to get a file handle, throw an Exception.
if ($fileHandle === false) {
throw new Exception('Could not get file handle for: ' . $file);
}
//While we haven't reach the end of the file.
while (!feof($fileHandle)) {
//Read the current line in.
$line = json_decode(fgets($fileHandle));
$rowProcessor($line);
}
//Finally, close the file handle.
fclose($fileHandle);
return $lines;
}
Then your will need different code that works with this:
function processAndWriteJson($filename) { //Names are hard
$writer = fopen('output.csv', 'w');
read($filename, function ($row) use ($writer) {
// Do processing of the single row here
fputcsv($writer, $processedRow);
});
}
If you want to get the same result as before with your read method you can do:
$lines = [];
read($filename, function ($row) use ($writer) {
$lines[] = $row;
});
It does provide some more flexibility. Unfortunately it does mean you can only process one line at a time and scanning up and down the file is harder

How do I record JSON data to file using PHP?

This is the code I've figured out.
<?php
$username = $_POST['username'];
$email = $_POST['email'];
$json = '{"username":"'.$username.'",'.'"email":"'.$email.'"}';
$file = fopen('token_data.json','w+');
fwrite($file, $json);
fclose($file);
?>
But this is absolutely not the right way.
If your $_POST array has all of the data you need you can encode it as JSON and write to a file:
<?php
$json = json_encode($_POST);
$file = fopen('token_data.json','w+');
fwrite($file, $json);
fclose($file);
?>
If you want to append to the file you will need to read the file into an array first, add the newer parts of the array then encode it again before writing back to the file just like my friend #Rizier123 describes.
Okay, I found a more efficient way to do this.
Original Answer
// read the file if present
$handle = #fopen($filename, 'r+');
// create the file if needed
if ($handle === null)
{
$handle = fopen($filename, 'w+');
}
if ($handle)
{
// seek to the end
fseek($handle, 0, SEEK_END);
// are we at the end of is the file empty
if (ftell($handle) > 0)
{
// move back a byte
fseek($handle, -1, SEEK_END);
// add the trailing comma
fwrite($handle, ',', 1);
// add the new json string
fwrite($handle, json_encode($event) . ']');
}
else
{
// write the first event inside an array
fwrite($handle, json_encode(array($event)));
}
// close the handle on the file
fclose($handle);
}
Without decoding the whole JSON file into the arrays.

Odd Behavior when appending JSON file using PHP

So I have a JSON file containing basketball player information in the following format:
[{"name":"Lamar Patterson","team":1,"yearsLeft":0,"position":"PG","PPG":17},{"name":"Talib Zanna", "team":1,"yearsLeft":0,"position":"SF","PPG":13.1},....]
I want a user to be a able to add their own custom players to this file. To do this i try the following:
<?php
$json = file_get_contents('json/players.json');
$info = json_decode($json, true);
$info[] = array('name'=>$name, 'team'=>$team, 'yearsLeft'=>4, 'position'=>$position, 'PPG'=>$ppg);
file_put_contents('json/players.json', json_encode($info));
?>
This "sort of" works. But when I check the JSON file, I find that there are 3 new entries rather than 1:
{"name":"","team":null,"yearsLeft":4,"position":"","PPG":""},{"name":"","team":"3","yearsLeft":4,"position":"","PPG":""},{"name":"Jeff","team":null,"yearsLeft":4,"position":"C","PPG":"23"}
assuming $name="Jeff" $team=3 and $ppg=23 (populated via POST submission).
What's going on and how can I fix it?
You could try doing the following:
Untested code
<?php
if(!empty($name) && !empty($team) && !empty($position) && !empty($ppg)) {
$fh = fopen('json/players.json', 'r+') or die("can't open file");
$stat = fstat($fh);
ftruncate($fh, $stat['size']-1);//removes last ] char
fclose($fh);
$fh = fopen('json/players.json', 'a');
$info = array('name'=>$name, 'team'=>$team, 'yearsLeft'=>4, 'position'=>$position, 'PPG'=>$ppg);
fwrite($fh, ','.json_encode($info).']');
fclose($fh);
}
?>
This will append the only the new json to the file instead of opening the file, making php parse all the json and then writing it to the file again. In addition to that it will only store the data if the variables actually contain data.
Try this:
<?php
//get the posted values
$name = $_POST['name'];
$team = $_POST['team'];
$position = $_POST['position'];
$ppg = $_POST['ppg'];
//verify they're not empty
if(!empty($name) && !empty($team) && !empty($position) && !empty($ppg)) {
//Open the file
$fh = fopen('json/players.json', 'r+') or die("can't open file");
//get file info/stats
$stat = fstat($fh);
//final desired size after trimming the trailing ']'
$size = $stat['size']-1;
//file has contents? then remove the trailing ']'
if($size>0) ftruncate($fh, $size);
//close the current handle
fclose($fh);
// reopen the file for append
$fh = fopen('json/players.json', 'a');
//build your data array
$info = array('name'=>$name, 'team'=>$team, 'yearsLeft'=>4, 'position'=>$position, 'PPG'=>$ppg);
//if this is not the first item on file
if($size>0) fwrite($fh, ','.json_encode($info).']'); //append with comma
else fwrite($fh, '['.json_encode($info).']'); //first item on file
fclose($fh);
}
?>
Maybe your php config is not set to convert the post/get variables to global variables. This happened to me a couple of times so I rather create the variables I'm expecting from the post/get request. Also watch out for the page encoding, from personal experience you could be getting empty strings there.

How to replace one line in php?

I have test.txt file, like this,
AA=1
BB=2
CC=3
Now I wanna find "BB=" and replace it as BB=5, like this,
AA=1
BB=5
CC=3
How do I do this?
Thanks.
<?php
$file = "data.txt";
$fp = fopen($file, "r");
while(!feof($fp)) {
$data = fgets($fp, 1024);
// You have the data in $data, you can write replace logic
Replace Logic function
$data will store the final value
// Write back the data to the same file
$Handle = fopen($File, 'w');
fwrite($Handle, $data);
echo "$data <br>";
}
fclose($fp);
?>
The above peace of code will give you data from the file and helps you to write the data back to the file.
Assuming that your file is structured like an INI file (i.e. key=value), you could use parse_ini_file and do something like this:
<?php
$filename = 'file.txt';
// Parse the file assuming it's structured as an INI file.
// http://php.net/manual/en/function.parse-ini-file.php
$data = parse_ini_file($filename);
// Array of values to replace.
$replace_with = array(
'BB' => 5
);
// Open the file for writing.
$fh = fopen($filename, 'w');
// Loop through the data.
foreach ( $data as $key => $value )
{
// If a value exists that should replace the current one, use it.
if ( ! empty($replace_with[$key]) )
$value = $replace_with[$key];
// Write to the file.
fwrite($fh, "{$key}={$value}" . PHP_EOL);
}
// Close the file handle.
fclose($fh);
The simplest way (if you are talking about a small file as above), would be something like:
// Read the file in as an array of lines
$fileData = file('test.txt');
$newArray = array();
foreach($fileData as $line) {
// find the line that starts with BB= and change it to BB=5
if (substr($line, 0, 3) == 'BB=')) {
$line = 'BB=5';
}
$newArray[] = $line;
}
// Overwrite test.txt
$fp = fopen('test.txt', 'w');
fwrite($fp, implode("\n",$newArray));
fclose($fp);
(something like that)
You can use Pear package for find & replace text in a file .
For more information read
http://www.codediesel.com/php/search-replace-in-files-using-php/

Using php, how to insert text without overwriting to the beginning of a text file

I have:
<?php
$file=fopen(date("Y-m-d").".txt","r+") or exit("Unable to open file!");
if ($_POST["lastname"] <> "")
{
fwrite($file,$_POST["lastname"]."\n");
}
fclose($file);
?>
but it overwrites the beginning of the file. How do I make it insert?
I'm not entirely sure of your question - do you want to write data and not have it over-write the beginning of an existing file, or write new data to the start of an existing file, keeping the existing content after it?
To insert text without over-writing the beginning of the file, you'll have to open it for appending (a+ rather than r+)
$file=fopen(date("Y-m-d").".txt","a+") or exit("Unable to open file!");
if ($_POST["lastname"] <> "")
{
fwrite($file,$_POST["lastname"]."\n");
}
fclose($file);
If you're trying to write to the start of the file, you'll have to read in the file contents (see file_get_contents) first, then write your new string followed by file contents to the output file.
$old_content = file_get_contents($file);
fwrite($file, $new_content."\n".$old_content);
The above approach will work with small files, but you may run into memory limits trying to read a large file in using file_get_conents. In this case, consider using rewind($file), which sets the file position indicator for handle to the beginning of the file stream.
Note when using rewind(), not to open the file with the a (or a+) options, as:
If you have opened the file in append ("a" or "a+") mode, any data you write to the file will always be appended, regardless of the file position.
A working example for inserting in the middle of a file stream without overwriting, and without having to load the whole thing into a variable/memory:
function finsert($handle, $string, $bufferSize = 16384) {
$insertionPoint = ftell($handle);
// Create a temp file to stream into
$tempPath = tempnam(sys_get_temp_dir(), "file-chainer");
$lastPartHandle = fopen($tempPath, "w+");
// Read in everything from the insertion point and forward
while (!feof($handle)) {
fwrite($lastPartHandle, fread($handle, $bufferSize), $bufferSize);
}
// Rewind to the insertion point
fseek($handle, $insertionPoint);
// Rewind the temporary stream
rewind($lastPartHandle);
// Write back everything starting with the string to insert
fwrite($handle, $string);
while (!feof($lastPartHandle)) {
fwrite($handle, fread($lastPartHandle, $bufferSize), $bufferSize);
}
// Close the last part handle and delete it
fclose($lastPartHandle);
unlink($tempPath);
// Re-set pointer
fseek($handle, $insertionPoint + strlen($string));
}
$handle = fopen("file.txt", "w+");
fwrite($handle, "foobar");
rewind($handle);
finsert($handle, "baz");
// File stream is now: bazfoobar
Composer lib for it can be found here
You get the same opening the file for appending
<?php
$file=fopen(date("Y-m-d").".txt","a+") or exit("Unable to open file!");
if ($_POST["lastname"] <> "")
{
fwrite($file,$_POST["lastname"]."\n");
}
fclose($file);
?>
If you want to put your text at the beginning of the file, you'd have to read the file contents first like:
<?php
$file=fopen(date("Y-m-d").".txt","r+") or exit("Unable to open file!");
if ($_POST["lastname"] <> "")
{
$existingText = file_get_contents($file);
fwrite($file, $existingText . $_POST["lastname"]."\n");
}
fclose($file);
?>

Categories