I need to create a JSON object using PHP, as I need to give attributes to each node like XML uses I can't just create a load of PHP arrays (I think), so I am creating PHP objects and doing that way.
The problem is I can quite get the JSON formatted properly.
This is what I am trying:
$object = new stdClass();
$object->{'0'}['title'] = 'Home';
$object->{'0'}['entry'] = '123';
$object->{'1'}['title'] = 'About';
$object->{'1'}['entry'] = '123';
$object->{'2'}['title'] = 'Gallery';
$object->{'2'}['entry'] = '123';
$object->{'2'} = new stdClass();
$object->{'2'}->{'0'}['title'] = 'Past';
$object->{'2'}->{'0'}['entry'] = '1234';
$object->{'2'}->{'1'}['title'] = 'Present';
$object->{'2'}->{'1'}['entry'] = '1235';
$object->{'2'}->{'0'} = new stdClass();
$object->{'2'}->{'0'}->{'0'}['title'] = '1989';
$object->{'2'}->{'0'}->{'0'}['entry'] = '12345';
$object->{'2'}->{'0'}->{'1'}['title'] = '1990';
$object->{'2'}->{'0'}->{'1'}['entry'] = '12346';
$ob=json_encode($object);
echo $ob;
Which outputs:
{
"0":{"title":"Home","entry":"123"},
"1":{"title":"About","entry":"123"},
"2":{
"0":{
"0":{"title":"1989","entry":"12345"},
"1":{"title":"1990","entry":"12346"}},
"1":{"title":"Present","entry":"1235"}
}
}
I need "2" of the first node to have attributes "title":"Gallery","entry":"123" but also contain the sub nodes for Past and Present, with the same again for the years.
In XML it may look something like this:
<0 title="Home" entry="123">
<0/>
<1 title="About" entry="123">
<1/>
<2 title="Gallery" entry="123">
<0 title="Past" entry="1234">
<0 title="1989" entry="12345"><0/>
<1 title="1990" entry="12346"><1/>
<0/>
<1 title="Present" entry="1235">
<1/>
<2/>
The easiest way to use json with PHP is to use the built in json_encode() and json_decode() functions.
This is really nice because you can encode php arrays straight into json without having to do anything!
$array = array(
array(
"title" => "Home",
"entry" => "123"
),
array(
"title" => "About",
"entry" => "123"
),
array(
"title" => "Gallery",
"entry" => "123",
),
);
And continue to nest as such, you can then convert that into a json object:
$json = json_encode($array);
With an output like:
[{"title":"Home","entry":"123"},{"title":"About","entry":"123"},{"title":"Gallery","entry":"123"}]
You can then access these again with php by doing a json_decode and moving around it like an object.
I made a playground for you to mess with here:
http://codepad.viper-7.com/qzMJO3
Hope that helps!
you're deleting them with your object creation:
swap these lines around:
$object->{'2'}['title'] = 'Gallery';
$object->{'2'}['entry'] = '123';
//this line creating the new object is effectively erasing the previous 2 lines.
$object->{'2'} = new stdClass();
to become:
$object->{'2'} = new stdClass();
$object->{'2'}['title'] = 'Gallery';
$object->{'2'}['entry'] = '123';
You're setting $object->{'2'} and $object->{'2'}->{'0'} with new stdClass(), loosing the data you've set previously.
Try this:
<?php
$object = new stdClass();
$object->{'0'}['title'] = 'Home';
$object->{'0'}['entry'] = '123';
$object->{'1'}['title'] = 'About';
$object->{'1'}['entry'] = '123';
$object->{'2'}['title'] = 'Gallery';
$object->{'2'}['entry'] = '123';
$object->{'2'}['0']['title'] = 'Past';
$object->{'2'}['0']['entry'] = '1234';
$object->{'2'}['1']['title'] = 'Present';
$object->{'2'}['1']['entry'] = '1235';
$object->{'2'}['0']['0']['title'] = '1989';
$object->{'2'}['0']['0']['entry'] = '12345';
$object->{'2'}['0']['1']['title'] = '1990';
$object->{'2'}['0']['1']['entry'] = '12346';
$ob=json_encode($object);
Related
I'm using Laravel to parse an XML file and store it into the DB. Now, it's probably some sort of a stupid mistake I can't put my finger on, but I would really appreciate if someone could check the code and the weird results I'm getting.
The XML has a deep and complex structure, here's a little piece from that's bugging me:
I'm dumping the $nizXMLsp in the end to see what's inside the array of objects:
public function upload(){
$dom = new DomDocument();
$nizBaza = DB::table('offers')->orderBy('id', 'DESC')->first();
$nizXML = array();
$objekat = new stdClass();
$dom->load("storage/X_Lista.xml");
$domXpath = new DomXPath($dom);
$upit = $domXpath->query('//offer');
foreach($upit as $of){
$objekat->Time = $of->getAttribute('Time');
$objekat->Date = $of->getAttribute('Date');
$objekat->betRound = $of->getAttribute('betRound');
$objekat->timestamp = $of->getAttribute('timestamp');
array_push($nizXML, $objekat);
}
if(is_null($nizBaza) or $nizBaza->id != $nizXML[0]->betRound) {
$kolo = new Offer();
$kolo->id = $objekat->betRound;
$kolo->ts = $objekat->Date . " " . $objekat->Time;
$kolo->posix = $objekat->timestamp;
$kolo->save();
//
$nizBaza = DB::table('sportovi')->get();
$nizXMLsp = array(); $objekat_sp = new stdClass();
foreach($dom->getElementsByTagName('sport') as $k=>$v){
$objekat_sp->id = $v->getAttribute('id');
$objekat_sp->name = $v->getAttribute('name');
$objekat_sp->betRound = $v->parentNode->getAttribute('betRound');
$nizXMLsp[$k] = $objekat_sp;
}
}
elseif($nizBaza->id == $nizXML[0]->betRound){
echo 'break1';
exit;
}
else {
echo 'break2';
exit;
}
return var_dump($nizXMLsp);
}
Now, what I see in the end is this:
instead of 4 objects with different sets of data, I get 4 objects with same set of data (all of the data comes from the last node). What could it be?
Possibly a very simple adjustment. Just reset $objekat_sp inside the loop:
foreach($dom->getElementsByTagName('sport') as $k=>$v){
$objekat_sp = "";
$objekat_sp->id = $v->getAttribute('id');
$objekat_sp->name = $v->getAttribute('name');
$objekat_sp->betRound = $v->parentNode->getAttribute('betRound');
$nizXMLsp[$k] = $objekat_sp;
}
Move
$objekat = new stdClass();
and
$objekat_sp = new stdClass();
inside their respective foreach loops.
Right now you're pushing the same object (after modifying its properties) into the array multiple times.
I'm trying to encode a json response using php, and having some trouble formatting it for use with ajax.
I'm basically trying to return an array of Rental objects, which each will include data for book, student, and teacher. Currently I'm using php to build objects like this...
while ($row = $result->fetch_array(MYSQLI_BOTH)) {
$obj = array();
// Build a book out of the results array, then push to the current object
$book = new Book();
$book->id = $row['book_id'];
$book->title = $row['title'];
$book->author = $row['author'];
$book->ar_quiz = $row['ar_quiz'];
$book->ar_quiz_pts = $row['ar_quiz_pts'];
$book->book_level = $row['book_level'];
$book->type = $row['type'];
$book->teacher_id = $row['teacher_id'];
array_push($obj, array('book' => $book));
// Build a student out of the results array, then push it to the current objects
$student = new Student();
$student->id = $row['student_id'];
$student->username = $row['student_username'];
$student->nicename = $row['student_nicename'];
$student->classroom_number = $row['classroom_number'];
array_push($obj, array('student' => $student));
// Build a teacher out of the results, push to current object
$teacher = new Teacher();
$teacher->id = $row['teacher_id'];
$teacher->username = $row['teacher_username'];
$teacher->nicename = $row['teacher_nicename'];
array_push($obj, array('teacher' => $teacher));
array_push($rentals, $obj);
}
mysqli_stmt_close($stmt);
return json_encode($rentals);
... building an $obj for each result, and then appending the whole $obj object to the end of $rentals, which is what I pass back in the end. Here is what the response looks like when I encode it to json:
[
[
{
"book":{
"id":113,
"title":"Book Test",
"author":"Test Test Author",
"ar_quiz":1,
"ar_quiz_pts":"10.0",
"book_level":"20.0",
"type":"Fiction",
"teacher_id":1
}
},
{
"student":{
"id":2,
"username":"studentnametest",
"classroom_number":2,
"nicename":"Student Name"
}
},
],
...
]
The problem here is that there is an extra {} around each of the book, student, and teacher objects, causing an extra step when trying to access in the javascript. For example, I think I have to use data[0].[0].book.title, when I really just want to be able to use data[0].book.title. How do I better structure this to fit my needs?
Don't add the additional array structure and you can simply change your array_push lines from
array_push($obj, array('book' => $book));
to
$obj['book'] = $book;
When creating a object in php used to return JSON is it possible to add a property and force it to go at the top? I'd like this since the object is exposed via an API and it is nice to have ids at the top.
For example:
$obj = new stdClass();
$obj->name = 'John';
$obj->age = 26;
$obj->id = 3645;
When you json_encode() this, it turns into:
{
"name": "John",
"age": 26,
"id": 3645
}
Is there a way to force id at the top of the object even though it is added last? Note, I can't simply just add id before adding name and age because of other dependent code.
It's easily possible if you use an associative array instead of an object, i.e.
$x = ['name' => 'john', 'age' => 26]; // or: $x = (array)$obj
$x = ['id' => 123] + $x;
echo json_encode($x);
// {"id":123,"name":"john","age":26}
However, it's important to note that in JSON property ordering is not defined and should not be relied upon. If what you currently have works, this change would be rather useless in fact.
Not very elegant but...
$obj = new stdClass();
$obj->name = 'John';
$obj->age = 26;
$obj->id = 3645;
$name = $obj->name;
$age = $obj->age;
unset($obj->name);
unset($obj->age);
$obj->name = $name;
$obj->age = $age;
echo json_encode($obj);
Hmm, nice question!
It is not possible to add a property and force it to go at the top.
You have to sort the object properties or the array keys.
Some nitpicking here: JSON is unordered by definition, but the browsers respect the insertion order. More: https://code.google.com/p/v8/issues/detail?id=164
JSON
4.3.3 Object An object is a member of the type Object. It is an unordered collection of properties each of which contains a
primitive value, object, or function. A function stored in a property
of an object is called a method.
Check this out: http://ideone.com/Hb4rGQ
<?php
function array_reorder_keys($array, $keynames){
if(empty($array) || !is_array($array) || empty($keynames)) return;
if(!is_array($keynames)) $keynames = explode(',',$keynames);
if(!empty($keynames)) $keynames = array_reverse($keynames);
foreach($keynames as $n){
if(array_key_exists($n, $array)){
$newarray = array($n=>$array[$n]); //copy the node before unsetting
unset($array[$n]); //remove the node
$array = $newarray + array_filter($array); //combine copy with filtered array
}
}
return $array;
}
$obj = new stdClass();
$obj->name = 'John';
$obj->age = 26;
$obj->id = 3645;
function get_json_sorted($object, $array) {
return json_encode(array_reorder_keys(get_object_vars($object), $array));
}
var_dump(get_json_sorted($obj, array('id', 'name', 'age')));
This is a solution. Turn the object into an assoc array. Get the last item (both key and value) off of the array (I'm assuming id is the last element) and move it to the front. Finally convert the assoc array back into an object.
$data_array = json_decode(json_encode($obj), true);
if(is_array($data_array)) {
end($data_array);
$data_array = array_merge(array(key($data_array) => array_pop($data_array)), $data_array);
$data = json_decode(json_encode($data_array), false);
}
This is a similar answer to Jacks' answer ( https://stackoverflow.com/a/24900322/6312186 ) but that caused a fatal error for me. I had to tweak it a bit by casting to array, using array_merge() and cast back to object, but this worked nicely for me:
$obj = (object) array_merge( (array)$obj2, (array)$obj);
This code is more generic and should work for all versions of PHP, including strict mode. Full code here
$obj = new stdClass(); // create new object
$obj->name = 'john';
$obj->age = '26';
$obj2 = new stdClass(); // we want to add this object to the top of $obj
$obj2->id = 'uid2039';
$obj = (object) array_merge( (array)$obj2, (array)$obj);
var_dump($obj);
// object(stdClass)#8700 (3) { ["id"]=> string(7) "uid2039" ["name"]=> string(4) "john" ["age"]=> string(2) "26" }
If you are json_encodeing this, you don't need to cast it back to an object again before encoding it:
$arr = ['name' => 'John', 'age' => '26'];
echo json_encode($arr);
// {"name":"john","age":"26"}
// is the same as:
$obj = (object)$arr;
echo json_encode($obj );
// {"name":"john","age":"26"}
When doing stdClass in PHP we can do it this way:
// Create new stdClass Object
$init = new stdClass;
// Add some test data
$init->foo = "Test data";
$init->bar = new stdClass;
$init->bar->baaz = "Testing";
$init->bar->fooz = new stdClass;
$init->bar->fooz->baz = "Testing again";
$init->foox = "Just test";
Is there any other alternative way to do with so that it looks cleaner like we can do with JavaScript?
Thanks.
$array = array('x'=>123);
$object = (object) $array;
This works when we do this:
$db = $connection->messages;
$collection = $db->messagesCollection;
$messageArray = $collection->find(array('IDto' => '4'));
foreach($messageArray as $messageData){
$messageFrom = $messageData['IDfrom'];
$messageTo = $messageData['IDto'];
$messageTitle = $messageData['messageTitle'];
$messageIfRead = $messageData['ifRead'];
}
$JSONData = array('true', $messageFrom, $messageTo, $messageTitle, $messageIfRead);
echo $_GET['callback']."(".json_encode($JSONData).")";
But when we do this:
$db = $connection->messages;
$collection = $db->messagesCollection;
$messageArray = $collection->find(array('IDto' => '4'));
$JSONData = array('true', $messageArray);
echo $_GET['callback']."(".json_encode($JSONData).")";
and in the Javascript do this:
$.getJSON("mySite.com/pullData/getMail.php?callback=?",{
request: requestVar},
function(recievedData) {
alert(recievedData);
})
We get an alert of true, [object Object]
When using console log we get Object {}
How do we send that table data correctly?
I believe your biggest problem is the MongoCursor:
$messageArray = $collection->find(array('IDto' => '4'));
$JSONData = array('true', $messageArray);
echo $_GET['callback']."(".json_encode($JSONData).")";
You are trying to encode an object of MongoCursor there, hence the string representation is [object Object].
Try:
$messageArray = $collection->find(array('IDto' => '4'));
$JSONData = array('true', iterator_to_array($messageArray));
echo $_GET['callback']."(".json_encode($JSONData).")";
Instead. All find functions in MongoDB return a MongoCursor, the reason why your first code works is because you iterate the cursor building up your objects:
foreach($messageArray as $messageData){
$messageFrom = $messageData['IDfrom'];
$messageTo = $messageData['IDto'];
$messageTitle = $messageData['messageTitle'];
$messageIfRead = $messageData['ifRead'];
}
Note as well that the default json_encode of a document will contain objects, such as MongoId and MongoDate that do not encode too well into reusable JSON syntax. As such you will need to handle these types yourself.
Edit
Maybe a better way is to actually redo the indexes manually:
$messageArray = $collection->find(array('IDto' => '4'));
$d = array();
foreach($messageArray as $row){
$d = $row;
}
$JSONData = array('true', $d);
echo $_GET['callback']."(".json_encode($JSONData).")";
This way you will have a 0 based incrementing index instead of the ObjectId as each index base.