php convert multidimensional array to json object - php

PHP NEWBIE
[PHP 7.4]
I am trying to refactor some old code.
GOAL: The two JSON must match.
Code snipppet 1: Old JSON code generated from php array
Code snippet 2: New JSON code generated from php array
Objective: Both must match, I am using php unit to compare them. For simplicity, I have removed the testing code.
PROBLEM: Extra set of square brackets, see image below.
I tried Using JSON_FORCE_OBJECT, which removes the square brackets, but introduces {... john: { "0": { "byEmail" ... " and ... "marie": { "1" { "byEmail" ...
(Naming wise: I have used John and marie, but these could be promotions, offers, packages, etc. so ignore the naming please)
SNIPPET 1 - php code
$body = [
"data" => [
"john" => [
"byEmail" => [
"status" => true,
"source" => "my-server",
],
"byPhoneCall" => [
"status" => true,
"source" => "my-server",
]
],
"marie" => [
"byEmail" => [
"status" => true,
"source" => "my-server",
],
"byPhoneCall" => [
"status" => true,
"source" => "my-server",
]
]
]
];
This gets converted to this JSON object:
// SNIPPET 1 - running json_encode()
{
"data": {
"john": {
"byEmail": {
"source": "my-server",
"status": true
},
"byPhoneCall": {
"source": "my-server",
"status": true
}
},
"marie": {
"byEmail": {
"source": "my-server",
"status": true
},
"byPhoneCall": {
"source": "my-server",
"status": true
}
}
}
}
SNIPPET 2:
I am creating this data structure dynamically now, because future requirement may have johnByPost, johnByFax, etc.:
//my-file-dynamic-generation.php
public function constructArray($johnByEmail=null, $johnByPhone=null, $marieByEmail=null, $marieByPhone=null) {
$body = [ "data" => ["john" => [], "marie" => []]];
if ($johnByEmail !== null) {
array_push($body["data"]["john"], $this->createKeyValuePair("byEmail", $johnByEmail));
}
if ($johnByPhone !== null) {
array_push($body["data"]["john"], $this->createKeyValuePair("byPhoneCall", $johnByPhone));
}
if ($marieByEmail !== null) {
array_push($body["data"]["marie"], $this->createKeyValuePair("byEmail", $marieByEmail));
}
if ($marieByPhone !== null) {
array_push($body["data"]["marie"], $this->createKeyValuePair("byPhoneCall", $marieByPhone));
}
return $body;
}
// HELPER func
function createKeyValuePair($title=null, $status=null, $source="my-server") {
return [
$title => [
"status" => $status,
"source" => $source,
]
];
}
JSON - OUTPUT
I have tried to use json_encode($data, JSON_FORCE_OBJECT)
That resulted me to get an extra key, which I don't want (I got .... [0] => 'marie' => ... [1] => 'john'
Appreciate reading this, thanks!

You are creating a new array inside the function createKeyValuePair() (probably to add the key). You could use the function the create the content only, and create the key inside the function constructArray() :
$body["data"]["john"]["byEmail"] = $this->createKeyValuePair($johnByEmail);
and the function :
function createKeyValuePair($status = null, $source = "my-server"): array
{
return [
"status" => $status,
"source" => $source,
];
}

Related

String into array

I have a string like:
{
"OperationResult": [
{
"CA::Read:PackageItems": {
"Read.PackageItem.RemoteBalanceAssigned": false,
"Read.PackageItem.CLSpvInfo": "1|-1#-9223372036854775000",
"PackageList":
[
"TopSim-4GSim1GBData",
"TopSim-ATBReactivation"
],
"PackageTypeList":
[
"optional-unsubscribed", "optional-unsubscribed"
],
"PackageFunctionalNameList":
[
"FreeUnits",
"AccumulationReward+MultipleThresholds"
],
"PackageSubStateList":
[
"",
""
],
"PackageEligibilityList":
[
true,
true
]
}
}]
}
I am trying to get it into array. but I want filter this string and only put PackageList":["xxxx-yyy","zzz-zzz"] and "PackageSubStateList":[TRUE,FALSE]}
Any thing in between should be filter out.
The resulted array should be like:
PackageList {
name: xxxx-yyy,
state: TRUE,
}
....
//The json posted in the question is invalid, assuming valid json gets used here afterwards:
$string = '{"OperationResult":[{"CA::Read:PackageItems":{"PackageList":["xxxx-yyy","zzz-zzz"],
"PackageTypeList":["optional-unsubscribed","optional-"optional-unsubscribed""],
"PackageFunctionalNameList":["FreeUnits","AccumulationReward+MultipleThresholds"],
"PackageSubStateList":[TRUE,FALSE]}';
$object = json_decode($string);
$wanted = $object['OperationResult']['CA::Read:PackageItems'];
$wanted should now contain what you need

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()
)
);

JSON object in PHP with property

What would be the equivalent PHP array structure to create an object with identical properties:
For example... create the object 'columns' below in PHP using json_encode:
jQuery('#example').dataTable( {
"ajaxSource": "sources/objects.txt",
"columns": [
{ "data": "engine" },
{ "data": "browser" },
{ "data": "platform" },
{ "data": "version" },
{ "data": "grade" }
]
} );
(I am trying to build a dynamic datatable and define the columns in the source JSON.
You could use an ArrayObject
new ArrayObject([
"ajaxSource" => "...",
"columns" => [
new ArrayObject(['data' => 'engine']),
new ArrayObject(['data' => 'browser']),
new ArrayObject(['data' => 'etc'])
]
]);
if you want to assemble this you need to store the objects inside an array like
$columns = [];
for(...) {
$columns[] = new ArrayObject(['data' => 'etc']);
}
Have a look at http://php.net/manual/de/arrayobject.construct.php

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.

Creat json data file for gallery file with php

I know this question was asked already for couple times, I've seen the answers but it already helped me a lot, but i need to solve one more problem regarding to this.
So the question is:
I need to build json file with php.
Here how looks my json file that i need:
{
"fashion":[
{
"alt":"Alisa",
"src":"img/fashion/Alisa/kubik.jpg",
"class":"albumItem",
"id":"FashionAlbum001",
"itemNum":0,
"album":[
{
"alt":"albumImg1",
"src":"img/fashion/Alisa/alisa1.jpg"
},
{
"alt":"albumImg1",
"src":"img/fashion/Alisa/alisa5.jpg"
},
{
"alt":"albumImg1",
"src":"img/fashion/Alisa/alisa7.jpg"
}
]
},
{
"alt":"2-Addis",
"src":"img/fashion/2-Addis/kubik.jpg",
"class":"albumItem",
"id":"FashionAlbum002",
"itemNum":1,
"album":[
{
"alt":"albumImg1",
"src":"img/fashion/2-Addis/addis1.jpg"
},
{
"alt":"albumImg4",
"src":"img/fashion/2-Addis/addis4.jpg"
}] } ] }
and so on...
I can't find out how to make a list of images inside each album
This is a php function a have
function buildJson(){
$json = json_encode(array(
"Fashion" => array(
"alt" => "Alisa",
"src" => "img/fashion/Alisa/kubik.jpg",
"id" => "FashionAlbum001",
"itemNum"=>"1",
"album"=>array(
"src"=>"img/fashion/Alisa/alisa1.jpg",
),
array(
"src"=>"img/fashion/Alisa/alisa5.jpg",
),
array(
"src"=>"img/fashion/Alisa/alisa7.jpg",
),
)
));
echo $json;
}
but I get json like this one:
{
"Fashion": {
"0": {
"src": "img/fashion/Alisa/alisa2.jpg"
},
"1": {
"src": "img/fashion/Alisa/alisa3.jpg"
},
"alt": "Alisa",
"src": "img/fashion/Alisa/kubik.jpg",
"id": "FashionAlbum001",
"itemNum": "0",
"album": {
"src": "img/fashion/Alisa/alisa1.jpg"
}
}
}
How is it possible to fix it?
Thank you!
Please pay more attention to the code you're writing :) Try to decode correct version of your json file and compare it to one you wrote. You should see some differences.
Your problem ir what follows after album key. You are assigning array with only one value to it instead of assigning array of arrays.
This is the way to go:
"album" => array(
array("src" => "img/fashion/Alisa/alisa1.jpg"),
array("src" => "img/fashion/Alisa/alisa5.jpg"),
array("src" => "img/fashion/Alisa/alisa7.jpg"),
),
you trouble in nesting album array
fixed code
function buildJson(){
$json = json_encode(
array(
"Fashion" => array(
"alt" => "Alisa",
"src" => "img/fashion/Alisa/kubik.jpg",
"id" => "FashionAlbum001",
"itemNum"=>"1",
// nesting error here
"album"=> array(
array("src"=>"img/fashion/Alisa/alisa1.jpg"),
array("src"=>"img/fashion/Alisa/alisa5.jpg"),
array("src"=>"img/fashion/Alisa/alisa7.jpg")
)
)
)
);
echo $json;
}

Categories