Correctly format JSON file - php

I'm trying to create a JSON file which contains objects and an array. Yet I'm missing the [ ]-brackets. I don't really know the exact terms for these JSON parts, which makes finding a solution using Google incredibly hard. I'm also a fairly new PHP coder, so I'm still learning. Any help or tips are really appreciated!
Code to create the JSON file:
$db_export = [
'account' => [
'username' => $username,
'email' => $email
]
];
file_put_contents("output.json", json_encode($db_export, JSON_PRETTY_PRINT));
Which outputs as:
{
"account": {
"username": "test",
"email": "test#domain.com"
}
}
What it's supposed to be:
{
"account": [
{
"username": "test",
"email": "test#domain.com"
}
]
}

Adding [] characters will help. This creates an array inside the array.
$db_export = [
'account' => [[ // <--- Added
'username' => $username,
'email' => $email
]] // <--- Added
];
file_put_contents("output.json", json_encode($db_export, JSON_PRETTY_PRINT));
This is how you get the result you want.
Output :
{ "account": [ { "username": null, "email": null } ] }
I guess it was a little simple :)

I am adding this to explain what is going on with the original answer. You can find this same information in the json_encode php manual page, in the example sections.
With any simple PHP array, json_encode will transform the PHP array into a JSON array:
$simple = array('apple', 'banana', 'coconut');
echo json_encode($simple);
Returns:
["apple","banana","coconut"]
Any associative array will be turned into a json object {} and each associative key will become a property name.
$associative = array('breakfast' => 'apple', 'lunch' => 'banana', 'dinner' => 'coconut');
echo json_encode($associative);
Returns:
{"breakfast":"apple","lunch":"banana","dinner":"coconut"}
In your example, you have an array with an associative key 'account' that contains an array with 2 child elements, each with an associative key.
This is the reason json_encode() is turning your structure into json objects.
In #Smokie's answer, the addition of an extra parent array that is "simple" ie. not keyed with a name, causes json_encode (following it's simple transformation rules) to create a javascript array, which it then sticks the javascript object inside of.
$username = 'test user';
$email = 'foo#bar.com';
$db_export = [
'account' => [[ // <--- Added
'username' => $username,
'email' => $email
]] // <--- Added
];
var_dump($db_export);
Returns:
array(1) {
["account"]=>
array(1) {
[0]=>
array(2) {
["username"]=>
string(9) "test user"
["email"]=>
string(11) "foo#bar.com"
}
}
}
Here I use var_dump as a quick debugging tool to show what the PHP array looks like. The important thing to note is that 'account' is now an array(1) with one element ( the 0th element) that contains your original child array.
Presumably you need this because the assumption is that an account could have multiple accountname/email address pairs. If that isn't the case, I would question why you need to force a useless array. I personally don't see how an 'account' could have multiple username/email pairs associated with it.
With that said, this code should further illustrate how this all works, and why:
$username = 'test user';
$email = 'foo#bar.com';
$db_export = [
'account' => [[ // <--- Added
'username' => $username,
'email' => $email
]] // <--- Added
];
//Add another username/email pair to account
$db_export['account'][] = ['username' => 'test2 user', 'email' => 'test2#bar.com'];
echo json_encode($db_export, JSON_PRETTY_PRINT);
Returns:
{
"account": [
{
"username": "test user",
"email": "foo#bar.com"
},
{
"username": "test2 user",
"email": "test2#bar.com"
}
]
}

Related

Getting data in particular format in PHP for Post request

I have to send some data in the below format-
$postData = [
'certExpiryDate' => $certExpiryDate,
'certType' => 'SSL',
'AltName' => [
$altName[0],$altName[1]
],
'csr' => $csr
];
$altName is an array that has 2 or more strings like- domain1.com, domain2.com.
The AltName parameter expects the data in this format-
'AltName' => [
'domain1.com','domain2.com'
],
(if I hardcode and send it like this, everything works fine.. this is the correct format)
If I take the array $altName directly like this-
'AltName' => [
$altName
],
I did a var_dump and for this it adds quotes outside like- "domain1.com, domain2.com", which it considers wrong.
I need it to be in the format of $altName[0],$altName[1] which would be correct, but I'm struggling on how to loop through this array in case it has more values than 2 and still get it in the required format.
Your attempt:
'AltName' => [
$altName
],
doesn't work as intended because it wraps the array $altName inside another array (created by the [ and ]).
Just set the $altName array to be the value of the property directly. There's no need for an extra array:
'AltName' => $altName
Demo: http://sandbox.onlinephpfunctions.com/code/fa3dd6a974be7ced4bdc5d878f692549b96e2b95
but I'm struggling on how to loop through this array in case it has
more values than 2 and still get it in the required format.
posting direct values:
//$altName = ["domain1.com", "domain2.com"];
//OR
$altName = array("domain1.com", "domain2.com");
$postData = ['AltName' => $altName];
var_dump($postData);
output:
array(1) {
["AltName"]=>
array(2) {
[0]=>
string(11) "domain1.com"
[1]=>
string(11) "domain2.com"
}
}

Changing the in-place value of array with PHP

I want to modify a value inside JSON. Let's say I have this example JSON and I want to have the php change the phone number:
$data = '{
"firstName": "John",
"lastName": "Smith",
"age": 27,
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
}
]
}'
It sounds like I have to convert to an array using json decode:
$data = json_decode($data,true);
Which gives me this:
array (
'firstName' => 'John',
'lastName' => 'Smith',
'age' => 27,
'phoneNumbers' =>
array (
0 =>
array (
'type' => 'home',
'number' => '212 555-1234',
),
),
)
How do I then insert my own variable value into the array please? From my googling it looks like I might be on the right path with something along these lines:
$number = '50';
$data[$key]['age'] = $number;
What it does though, is just add it onto the end of the array, instead of correcting the value in place of the array file.
Firstly, you need to convert your json to PHP array usign json_decode function. check below code for updating/inserting keys:
$data['age'] = $number; // to update age
$data['newkey'] = 'newvalue'; //it will add key as sibling of firstname, last name and further
$data['phoneNumbers'][0]['number'] = '222 5555 4444'; //it will change value from 212 555-1234 to 222 5555 4444.
You just need to consider array format. If key exists then you can update value else it will be new key in array. Hope it helps you.

Generate php array definition from JSON

My question is a bit different to most like this, I basically want to do the opposite to this question from Haluk.
So I have a JSON string:
{
"main":
{
"title": "QuickPub",
"defaultRole": "BU"
},
"roles":
{
"TU":
{
"name": "testUser",
"code": "TU"
}
}
}
and I want to be able to generate a string containing a php array definition from it:
<?php
return [
"main" =>
[
"title" => "QuickPub",
"defaultRole" => "BU"
],
"roles" =>
[
"TU" =>
[
"name" => "testUser",
"code" => "TU"
]
]
];
?>
EDIT:
I have tried json_decode() but this produces a variable, I need a string that I can put in a php file that will reproduce this without using php_decode.
I think this will solve your problem. First of all convert your json string to an array using json_decode($string,1); then convert that array to string representation using print_r($array,1); this will return your result as array string representation.
For example:
$json='{}' // its a demo
$array= json_decode($json,1); // an array
$result = print_r($array,1);
echo $result;
This is an adaptation of Being Sunny's answer, but using the var_export() function rather than print_r.
As described here by phihad
var_export prints valid php code. Useful if you calculated some values and want the results as a constant in another script
the script:
$json = '{"main":{"title": "QuickPub","defaultRole": "BU"},"roles":{"TU":{"name": "testUser","code": "TU"}}}';
$array = json_decode($json, 1);
$result = var_export($array, 1);
echo $result;
produces:
array(
'main' => array(
'title' => 'QuickPub',
'defaultRole' => 'BU',
),
'roles' => array(
'TU' => array(
'name' => 'testUser',
'code' => 'TU',
),
),
)
This can be achieved using this code:
$output = 'return ' . rtrim(preg_replace(['/{/', '/}/', '/:/'], ['[', ']', ' =>'], $json)) . ';';
this replaces { with [, } with ], and : with =>, trims any whitespace from the end, appends a ; and prepends a return statement.
this produces the output requested in the question bar the open and closing php tags.

Convert PHP to JSON with Nested Array

I have a PHP variable I need to convert to JSON string.
I have following PHP code:
$username="admin";
$password="p4ssword";
$name="Administrator";
$email="myname#smsfree4all.com"
$params=compact('username', 'password','name','email', 'groups');
json_encode($params);
This works fine. But what I am not sure about is how do I encode the properties in PHP with nested key value pairs shown below:
{
"username": "admin",
"password": "p4ssword",
"name": "Administrator",
"email": "admin#example.com",
"properties": {
"property": [
{
"#key": "console.rows_per_page",
"#value": "user-summary=8"
},
{
"#key": "console.order",
"#value": "session-summary=1"
}
]
}
}
What is this with # before key value?
Something like this should do it
$username="admin"; //more variables
$params=compact('username' /* more variables to be compacted here*/);
$params["properties"] = [
"property" => [
[
"#key" => "console.rows_per_page",
"#value"=> "user-summary=8"
],
[
"#key"=> "console.order",
"#value"=> "session-summary=1"
]
]
];
echo json_encode($params);
The manual has more examples you can use
Notice that:
A key~value array is encoded into an object
A regular array (array of arrays here) is encoded into an array
Those are all the rules you need to consider to encode any arbitrary object
Something like this perhaps?
$properties = [
'property' => [
['#key' => 'console.rows_per_page', '#value' => 'user-summary=8'],
['#key' => 'console.order', '#value' => 'session-summary=1']
]
];
It's difficult to tell what you're asking.
You can nest in PHP using simple arrays, very similar to JavaScript objects:
$grandparent = array(
"person1" => array(
"name" => "Jeff",
"children" => array(
array("name" => "Matt"),
array("name" => "Bob")
)
),
"person2" => array(
"name" => "Dillan",
"children" => array()
)
);

Unset object variable's property in a method, affected its value in parent scope?

I made a small library to read database-exported xml file, and output it as an structured associate array. It can also filter the output by table columns.
After I've done the code, when I play with this class I find something weird. unset is acting as if the variable was passed by reference.
I could not spot any possible bugs, so I put up my the particular method where $this->rows is being set, hoping someone could enlight me.
private function populateData($rowLimit)
{
if (!$this->getColumns()) {
throw new ReaderException(__FUNCTION__ . " # Unable to get columns name.");
}
// database->tableName->rows
$rows = $this->getSimpleXmlElement()->children()->children();
if ($this->getFilteredColumns()) {
$toRemoves = array_values(array_diff($this->getColumns(),
$this->getFilteredColumns()));
foreach ($rows as $row) {
foreach ($toRemoves as $toRemove) {
unset($row->{$toRemove});
}
}
}
$rows = $this->simpleXmlToArray($rows)['row'];
if ($rowLimit) {
$limited = [];
for ($i = 0; $i < $rowLimit; $i++) {
$limited[] = $rows[$i];
}
$this->setRows($limited);
} else {
$this->setRows($rows);
}
$structArray = [
'database' => $this->getDatabaseName(),
'table' => $this->getTableName(),
'columns' => !$this->getFilteredColumns() ? $this->getColumns()
: $this->getFilteredColumns(),
'rows' => $this->getRows()
];
$this->setStruct($structArray);
return $this;
}
$xml = new SomeXmlReader($companyTableFilePath);
$xml->get(1);
output:
[
"database" => "myDatabase",
"table" => "companies",
"columns" => [
"id",
"name",
"license_no",
"phone",
"created",
"modified",
],
"rows" => [
[
"id" => "1",
"name" => "SOME COMPANY NAME",
"license_no" => "884652",
"phone" => null,
"created" => "2015-09-25 16:01:57",
"modified" => "2015-09-25 16:01:57",
],
],
]
When I tried to filter off some columns, I do
$xml->setFilteredColumns(['id','name'])->get(1);
it returns the result as expected: the columns have been trimmed.
Output:
[
"database" => "myDatabase",
"table" => "companies",
"columns" => [
"id",
"name",
],
"rows" => [
[
"id" => "1",
"name" => "SOME COMPANY NAME",
],
],
]
However, right after this line, when I test it again with
$xml->setFilteredColumns(['id','name','phone'])->get(1);
on the next line, something went wrong. The output is:
[
"database" => "myDatabase",
"table" => "companies",
"columns" => [
"id",
"name",
"phone",
],
"rows" => [
[
"id" => "1",
"name" => "SOME COMPANY NAME",
],
],
]
After some tracing, I find that $this->getSimpleXmlElement() had been modified by unset. Within this app lifecycle, I can no longer get the complete/original value of $this->getSimpleXmlElement().
Is there a fundamental mistake I've made, or this is a PHP language behaviour?
There is rather a lot of code to follow through here - consider making a more compact example - but it sounds like your misunderstanding is fairly simple.
Objects are never copied when going from one scope to another, because a variable doesn't "contain" an object, it "points at" one (this is not quite the same as pass-by-reference, but the effect is similar in many cases).
So when you run unset($row->{$toRemove});, you are indeed editing the $row object, and by extension the whole SimpleXML document.
If you want a copy of an object to work with, you have to explicitly "clone" it, as discussed in the PHP manual.

Categories