PHP convert CSV to JSON multi level - php

I have a CSV data looks like this :
ps.csv
id|firstName|lastName|address|extId|extName
001|Kapil|Parames|address01|AA01|AA
002|David|Vuitton|address01|AA02|AA
002|David|Vuitton|address02|BB02|BB
003|Jean|Paul|address01|AA03|AA
And i need an output JSON to look like this :
[
{
"id": "001",
"firstName": "Kapil",
"lastName": "Parames",
"address": [{
"address": "address01"
}],
"ext": [{
"extId": "AA01",
"extName": "AA"
}]
},
{
"id": "002",
"firstName": "David",
"lastName": "Vuitton",
"address": [{
"address": "address01"
},
{
"address": "address02"
}
],
"ext": [{
"extId": "AA02",
"extName": "AA"
},
{
"extId": "BB02",
"extName": "BB"
}
]
},
{
"id": "003",
"firstName": "Jean",
"lastName": "Paul",
"address": [{
"address": "address01"
}],
"ext": [{
"extId": "AA03",
"extName": "AA"
}]
}
]
I can convert it to JSON. But the problem is i would like to add "address" and "extId", "extName" into multi level array if the person already exists in the list.

So following PHP code is working for me :
$csv = file('ps.csv');
$csvArray = [];
foreach ($csv as $line) {
$csvArray[] = str_getcsv($line, '|', ',');
}
$jsonArray = [];
for ($i = 1; $i < count($csvArray); $i++) {
$found = -1;
for ($j = 0; $j < count($jsonArray); $j++) {
if (in_array($csvArray[$i][0], $jsonArray[$j])) {
$found = $j;
}
}
if ($found < 0) {
$jsonArray[] = array(
'id' => $csvArray[$i][0],
'firstName' => $csvArray[$i][1],
'lastName' => $csvArray[$i][2],
'address' => array(
[
'address' => $csvArray[$i][3]
]
),
'ext' => array(
[
'extId' => $csvArray[$i][4],
'extName' => $csvArray[$i][5]
]
)
);
} else {
$addressArray = array(
'address' => $csvArray[$i][3]
);
$extArray = array(
'extId' => $csvArray[$i][4],
'extName' => $csvArray[$i][5]
);
array_push($jsonArray[$found]['address'], $addressArray);
array_push($jsonArray[$found]['ext'], $extArray);
}
}
echo '<pre>';
echo json_encode($jsonArray, JSON_PRETTY_PRINT);
echo '</pre>';
Is that correct or is there any other way to do ?

Related

merge array keys and add the values-PHP

I want to merge two same keys in an array and get the sum of the values.
I want the same structure as it is now.Because this data needs to be converted to JSON.
This is what i get now.
{
"data": [{
"count_of_invites": 5,
"user": "Rajesh",
"id": "53"
},
{
"count_of_invites": 9,
"user": "Student",
"id": "45"
},
{
"count_of_invites": 4,
"user": "Student",
"id": "45"
}
]
}
As you can see the id 45 are repeated.As i want the result as,
Expected output
{
"data": [{
"count_of_invites": 5,
"user": "Rajesh",
"id": "53"
},
{
"count_of_invites": 13,
"user": "Student",
"id": "45"
}
]
}
As you can see the duplicate entry should be removed as well as the count_of_invites of duplicate entry should be added.
<?php
$data = [
[
'id' => 2,
'name' => 'Paul',
'count' => 4
],
[
'id' => 3,
'name' => 'Peter',
'count' => 5
],
[
'id' => 3,
'name' => 'Peter',
'count' => 7
]
];
foreach($data as $array)
$counts[$array['id']][] = $array['count'];
$counts = array_map('array_sum', $counts);
foreach($data as $k => $array)
$data[$k]['count'] = $counts[$array['id']];
$data = array_unique($data, SORT_REGULAR);
print json_encode($data, JSON_PRETTY_PRINT);
Output:
[
{
"id": 2,
"name": "Paul",
"count": 4
},
{
"id": 3,
"name": "Peter",
"count": 12
}
]
You can achieve it this way:
$ids = array();
$output = array();
foreach ($input as $value) {
if (!isset($ids[$value["id"]])) {
$ids[$value["id"]]=$count($output);
$output[]=$value;
} else {
$output[$ids[$value["id"]]]["count_of_invites"] = $value["count_of_invites"];
$output[$ids[$value["id"]]]["user"] = $value["user"];
}
}
The count method was declared as variable and i've added with addition assignment operator.
Thank You for helping.
$ids = array();
$output = array();
foreach ($response as $value) {
if (!isset($ids[$value["id"]])) {
$ids[$value["id"]] = count($output);
$output[] = $value;
}
else {
$output[$ids[$value["id"]]]["count_of_invites"] += $value["count_of_invites"];
$output[$ids[$value["id"]]]["user"] = $value["user"];
}
}

Converting a JSON string to a JSON array

I have a CSV file like this
first_name,last_name,phone
Joseph,Dean,2025550194
Elbert,Valdez,2025550148
Using this csv-to-json.php from GitHub I get output like this
[{
"first_name": "Joseph",
"last_name": "Dean",
"phone": "2025550194",
"id": 0
}, {
"first_name": "Elbert",
"last_name": "Valdez",
"phone": "2025550148",
"id": 1
}]
This is almost what I want - however instead of
"phone": "2025550194"
I need
"phone": [{
"type": "phone",
"number": "2025550194"
}]
How do I correct this?
If you get the JSON string, then you would of course first convert it to an array with:
$arr = json_decode($json, true);
But probably you already have the array. You then apply this loop to it:
foreach($arr as &$row) {
if (isset($row['phone'])) { // only when there is a phone number:
$row['phone'] = [[ "type" => "phone", "number" => $row['phone'] ]];
}
}
See it run on eval.in.
You can change the csv-to-json.php code with following and you got the output that you want :-
Option 1 :-
// Bring it all together
for ($j = 0; $j < $count; $j++) {
$d = array_combine($keys, $data[$j]);
if ($j == 'phone') {
$newArray[$j] = array('type' => $j, 'number' => $d);
} else {
$newArray[$j] = $d;
}
}
Option 2 :-
$json_response = [{
"first_name": "Joseph",
"last_name": "Dean",
"phone": "2025550194",
"id": 0
}, {
"first_name": "Elbert",
"last_name": "Valdez",
"phone": "2025550148",
"id": 1
}];
$result = json_decode($json_response);
$final_result = array();
foreach ($result as $row) {
$row['phone'] = array('type' => 'phone', 'number' => $row['phone']);
$final_result[] = $row;
}
echo json_encode($final_result);
It may help you.

Add array elements in an array position

How can I add an array to array position:
Something like a:
<?php
$newArr = array('email' => array("id" => "5678", "token" => "fghjk"));
$arr = array(
"auth"=>
array(
'users'=>
array(
'id' =>"456yhjoiu",
'token' => "asdfghjkrtyui678"
)
)
);
somefunction($arr['auth'], $newArr);
I've tried array_push() but it added zero (0) before 'email' instead.~
I'm doing this to get a json output, something like this:
}
"auth": {
"users": {
"id": "456yhjoiu",
"token": "asdfghjkrtyui678"
},
"email": {
"id": "5678",
"token": "fghjk"
}
}
}
but I have this output:
{
"auth": {
"users": {
"id": "456yhjoiu",
"token": "asdfghjkrtyui678"
},
"0": {
"email": {
"id": "5678",
"token": "fghjk"
}
}
}
$data = ['auth' => array_merge($arr['auth'], $newArr)];
or old array notation <= PHP5.3
$data = array('auth' => array_merge($arr['auth'], $newArr));

PHP - Nested array keys based on string lines

I need a help. I'm looking for a solution for this problem!
I have a file which contains the following pattern:
Brazil|SaoPaulo|Diadema|RuadaFe Brazil|SaoPaulo|Diadema|RuadoLimoeiro
Brazil|SaoPaulo|SaoCaetano|RuadasLaranjeiras
Brazil|Parana|Curitiba|ComendadorAraujo
USA|NewJersey|JerseyCity|WhashingtonBoulervard
USA|NewJersey|JerseyCity|RiverCourt
Which should bring after some array key implementation, something like this (after apply json_encode call on php):
{
"name": "Brazil",
"children": [
{
"name": "SaoPaulo",
"children": [
{
"name": "Diadema",
"children": [
{"name": "RuadaFe"},
{"name": "RuadoLimoeiro"}
]
},
{
"name": "SaoCaetano",
"children": [
{"name": "RuadasLaranjeiras"}
]
},
]
"name": "Parana",
"children": [
{
"name": "Curitiba",
"children": [
{"name": "ComendadorAraujo"}
]
}
]
},
"name":"USA",
"children":[
{
"name": "NewJersey",
"children": [
{
"name": "JerseyCity",
"children": [
{"name": "WhashingonBoulevard"},
{"name": "RiverCourt"}
]
}
]
}
]
}
]
And keep going and going (and even more deeper too).
Please, help me team... thanks in advance.
Here what I get until now:
Array
(
[Brazil] => Array
(
[SaoPaulo] => Array
(
[Diadema] => Array
(
[RuadoLimoeiro] =>
)
[SaoCaetano] => Array
(
[RuadasLaranjeiras] =>
)
)
[Parana] => Array
(
[Curitiba] => Array
(
[ComendadorAraujo] =>
)
)
)
[USA] => Array
(
[NewJersey] => Array
(
[JerseyCity] => Array
(
[WhashingtonBoulervard] =>
[RiverCourt] =>
)
)
)
)
And here is the json encoded:
{
"Brazil":{
"SaoPaulo":
{"Diadema":
{"RuadoLimoeiro":null},
"SaoCaetano":{"RuadasLaranjeiras":null}
},
"Parana":
{"Curitiba":
{"ComendadorAraujo":null}
}
},
"USA":{
"NewJersey":{
"JerseyCity":{
"WhashingtonBoulervard":null,
"RiverCourt":null}
}
}
}
As you can see, the "names" and "child" is missing because is not an array key structure, also something is wrong, because I'm missing some values on SaoPaulo.
Here is the function:
foreach($strings as $string) {
$parts = array_filter(explode('|', $string));
$ref = &$result;
foreach($parts as $p) {
// echo $p;
if(!isset($ref[$p])) {
$ref[$p] = array();
// $ref[$p] = array("name"=>$p);
}
$ref = &$ref[$p];
}
$ref = null;
}
-------------------------------- AFTER SOME ANSWERS --------------------------
{
"name": "Brazil(country)",
"children": [
{
"name": "SaoPaulo(state)", // only one state
"children": [
{
"name": "Diadema(city)", // only one city
"children": [
{"name": "RuadaFe(street)"}, // two streets under the same city...
{"name": "RuadoLimoeiro(street)"}
]
},
{
"name": "SaoCaetano(city)",
"children": [
{"name": "RuadasLaranjeiras(street)"}
]
},
]
"name": "Parana(state)",
"children": [
{
"name": "Curitiba(city)",
"children": [
{"name": "ComendadorAraujo(street)"}
]
}
]
},...
I put on parentesis the structure (country, state, city, street) just to clarify what i want.
Got it?
It is not outright trivial, but what I did is actually the same as you (the same way as in your edited question), but I also keep track of those arrays to rename the keys. And that's what I do afterwards then:
$separator = [' ', '|'];
$buffer = file_get_contents($file);
$entries = explode($separator[0], $buffer);
$result = [];
$named[] = &$result;
########
foreach ($entries as $entry) {
$each = explode($separator[1], $entry);
$pointer = & $result;
while ($current = array_shift($each)) {
if (!isset($pointer[$current])) {
unset($children);
$children = [];
$named[] = &$children;
########
$pointer[$current] = ['name' => $current, 'children' => &$children];
}
$pointer = & $pointer[$current]['children'];
}
}
foreach($named as $offset => $namedArray) {
$keys = array_keys($namedArray);
foreach($keys as $key) {
$named[$offset][] = &$namedArray[$key];
unset($named[$offset][$key]);
}
}
print_r($result);
See it in action.
You probably might want to modify this by checking in the later foreach if children are empty (leaf-nodes) and then removing the children entry as well.
Here the modified foreach at the end and json output:
foreach($named as $offset => $namedArray) {
$keys = array_keys($namedArray);
foreach($keys as $key) {
if (!$namedArray[$key]['children']) {
unset($namedArray[$key]['children']);
}
$named[$offset][] = &$namedArray[$key];
unset($named[$offset][$key]);
}
}
echo json_encode($result, JSON_PRETTY_PRINT);
Output:
[
{
"name": "Brazil",
"children": [
{
"name": "SaoPaulo",
"children": [
{
"name": "Diadema",
"children": [
{
"name": "RuadaFe"
},
{
"name": "RuadoLimoeiro"
}
]
},
{
"name": "SaoCaetano",
"children": [
{
"name": "RuadasLaranjeiras"
}
]
}
]
},
{
"name": "Parana",
"children": [
{
"name": "Curitiba",
"children": [
{
"name": "ComendadorAraujo"
}
]
}
]
}
]
},
{
"name": "USA",
"children": [
{
"name": "NewJersey",
"children": [
{
"name": "JerseyCity",
"children": [
{
"name": "WhashingtonBoulervard"
},
{
"name": "RiverCourt"
}
]
}
]
}
]
}
]
The full code-example at a glance:
<?php
/**
* PHP - Nested array keys based on string lines
* #link http://stackoverflow.com/a/16305236/2261774
*/
$file = 'data://text/plain;base64,' . base64_encode('Brazil|SaoPaulo|Diadema|RuadaFe Brazil|SaoPaulo|Diadema|RuadoLimoeiro Brazil|SaoPaulo|SaoCaetano|RuadasLaranjeiras Brazil|Parana|Curitiba|ComendadorAraujo USA|NewJersey|JerseyCity|WhashingtonBoulervard USA|NewJersey|JerseyCity|RiverCourt');
$separator = [' ', '|'];
$buffer = file_get_contents($file);
$entries = explode($separator[0], $buffer);
$result = [];
$named[] = &$result;
foreach ($entries as $entry) {
$each = explode($separator[1], $entry);
$pointer = & $result;
while ($current = array_shift($each)) {
if (!isset($pointer[$current])) {
unset($children);
$children = [];
$named[] = &$children;
$pointer[$current] = ['name' => $current, 'children' => &$children];
}
$pointer = & $pointer[$current]['children'];
}
}
unset($pointer);
foreach($named as $offset => $namedArray) {
$keys = array_keys($namedArray);
foreach($keys as $key) {
if (!$namedArray[$key]['children']) {
unset($namedArray[$key]['children']);
}
$named[$offset][] = &$namedArray[$key];
unset($named[$offset][$key]);
}
}
unset($named);
echo json_encode($result, JSON_PRETTY_PRINT);
your question JSON:
{
"name": "Brazil",
"children": [
{
"name": "SaoPaulo",
"children": [
{
"name": "Diadema",
"children": [
{"name": "RuadaFe"},
{"name": "RuadoLimoeiro"}
]
},
My Answer JSON:
[
{
"name": "Brazil",
"children": [
{
"name": "SaoPaulo",
"children": [
{
"name": "Diadema",
"children": [
{
"name": "RuadaFe"
},
{
"name": "RuadoLimoeiro"
}
]
},
The only difference I can spot is that the root-nodes are wrapped inside an array in my answer, but it should be trivial to fetch them out there if that really is your issue ;)
Does it solves your problem? Use $inputString to put your real string.
<?php
// ------------------------------------------------------ your input goes here ------------------------------------------------------
$inputString = 'Brazil|SaoPaulo|Diadema|RuadaFe Brazil|SaoPaulo|Diadema|RuadoLimoeiro Brazil|SaoPaulo|SaoCaetano|RuadasLaranjeiras Brazil|Parana|Curitiba|ComendadorAraujo USA|NewJersey|JerseyCity|WhashingtonBoulervard USA|NewJersey|JerseyCity|RiverCourt';
class item {
public $name = null;
public function getChildrenByName($strName) {
$ret = null;
# this variable should be defined in interface, but i skipped it so it wont be printed in json when obj does not have childrens
if( !isset( $this->children ) ) {
$this->children = array( );
}
foreach ( $this->children as $child ) {
if( $child->name === $strName ) {
$ret = $child;
break;
}
}
if ( !$ret ) {
$this->children[] = self::spawnByName( $strName );
}
return $this->children[ count($this->children) - 1];
}
static public function spawnByName($strName) {
$ret = new item();
$ret->name = $strName;
return $ret;
}
}
class listManager {
protected $list = array();
public function getList() {
return $this->list;
}
public function addPath( $desiredPath ) {
# path needs to be as array
if ( is_string( $desiredPath ) ) {
$desiredPath = explode('|', $desiredPath);
}
# create root element if it does not already exists
if ( !isset( $this->list[$desiredPath[0]] ) ) {
$this->list[$desiredPath[0]] = item::spawnByName($desiredPath[0]);
}
$curElement = $this->list[$desiredPath[0]];
for( $i=1; $i<count($desiredPath); $i++ ) {
$curElement = $curElement->getChildrenByName( $desiredPath[$i] );
}
}
protected function spawnElement( $strName ) {
$ret = new item();
$ret->name = $strName;
return $ret;
}
}
$output = array();
$expl = explode(' ', $inputString);
$list = new listManager();
foreach ( $expl as $key => $path ) {
$list->addPath( $path );
}
$output = '';
foreach ( $list->getList() as $singleVariable ) {
$output .= json_encode($singleVariable, JSON_PRETTY_PRINT) . ",\n";
}
echo '<pre>'.$output.'</pre>';
?>
Above code produces following json out of your sample code:
{
"name": "Brazil",
"children": [{
"name": "SaoPaulo",
"children": [{
"name": "Diadema",
"children": [{
"name": "RuadaFe"
}
]
}
]
}, {
"name": "SaoPaulo",
"children": [{
"name": "Diadema",
"children": [{
"name": "RuadoLimoeiro"
}
]
}
]
}, {
"name": "SaoPaulo",
"children": [{
"name": "SaoCaetano",
"children": [{
"name": "RuadasLaranjeiras"
}
]
}
]
}, {
"name": "Parana",
"children": [{
"name": "Curitiba",
"children": [{
"name": "ComendadorAraujo"
}
]
}
]
}
]
} {
"name": "USA",
"children": [{
"name": "NewJersey",
"children": [{
"name": "JerseyCity",
"children": [{
"name": "WhashingtonBoulervard"
}
]
}
]
}, {
"name": "NewJersey",
"children": [{
"name": "JerseyCity",
"children": [{
"name": "RiverCourt"
}
]
}
]
}
]
}
edit: changed, does it fit now?

PHP Adjacency List to Nested Array

I am trying to convert following table data into nested array using PHP. I am almost done but stuck at one point.
id name parent
1 Apparel
2 Appliances
46 Apparel 1
47 Child Apparel 46
49 Child Apparel 2 47
Using this code
$cats = array(); // from database
$refs = array();
$rcats = array();
foreach ($cats as $cat) {
$thisref = &$refs[$cat['id']];
$thisref['id'] = $cat['id'];
$thisref['name'] = $cat['name'];
$thisref['leaf'] = "true";
if (!$cat['parent']) {
$rcats[$cat['id']] = &$thisref;
} else {
unset($refs[$cat['parent']]['leaf']);
$refs[$cat['parent']]['items'][$cat['id']] = &$thisref;
}
}
print_r(json_encode($rcats));
This results into following JSON.
{
"1": {
"id": "1",
"name": "Apparel",
"items": {
"46": {
"id": "46",
"name": "Apparel",
"items": {
"47": {
"id": "47",
"name": "Child Apparel",
"items": {
"49": {
"id": "49",
"name": "Child Apparel 2",
"leaf": "true"
}
}
}
}
}
}
},
"2": {
"id": "2",
"name": "Appliances",
"leaf": "true"
}
}
Where as I want the JSON like
[
{
"id": "1",
"name": "Apparel",
"items": [
{
"id": "46",
"name": "Apparel",
"items": [
{
"id": "47",
"name": "Child Apparel",
"items": [
{
"id": "49",
"name": "Child Apparel 2",
"leaf": "true"
}
]
}
]
}
]
},
{
"id": "2",
"name": "Appliances",
"leaf": "true"
}
]
Am i wrong? :p
$cats = array(); // From Database, but i use this
$cats = array(
array(
'id' => 1,
'name' => 'Jakarta',
'parent' => NULL
),
array(
'id' => 2,
'name' => 'Bandung',
'parent' => 1
),
array(
'id' => 3,
'name' => 'Surabaya',
'parent' => 1
),
array(
'id' => 4,
'name' => 'Bali',
'parent' => NULL
),
array(
'id' => 5,
'name' => 'Batam',
'parent' => NULL
),
);
$refs = array();
$rcats = array();
foreach ($cats as $cat) {
$thisref = &$refs[$cat['id']];
$thisref['id'] = $cat['id'];
$thisref['name'] = $cat['name'];
$thisref['leaf'] = "true";
if (!$cat['parent']) {
$rcats[] = &$thisref;
}
else {
unset($refs[$cat['parent']]['leaf']);
$refs[$cat['parent']]['items'][] = &$thisref;
}
}
/*
// IF YOU NEED CHANGE TO OBJECT
$rcats = (object)$rcats;
if(isset($rcats->items)){
$rcats->items = (object)$rcats->items;
}
*/
header('Content-type: application/json');
print_r(json_encode($rcats));
Here I'm assuming you are storing your final results in $refs
print_r(json_encode(array_values($rcats)));
If you want to take out all the indexes, in your for loop, do [] instead of the id:
if (!$cat['parent']) {
$rcats[] = &$thisref;
} else {
unset($refs[$cat['parent']]['leaf']);
$refs[$cat['parent']]['items'][] = &$thisref;
}
A quick example I throw:
<?php
$a = array('1' => array('a' => 3), '2' => array('b' => 4));
echo json_encode($a) . "\n";
echo json_encode(array_values($a)) . "\n";
Outputs:
{"1":{"a":3},"2":{"b":4}}
[{"a":3},{"b":4}]

Categories