JSON will not show?

Hi all

Tried everything trying to output my json data, without success :frowning:

No errors are showing and everything prints ok with var_dump etc. just can’t figure out what I’m doing wrong?

Snippet of JSON, reduced for viewing:

{
  "VCALENDAR": [
    {
      "METHOD": "PUBLISH",
      "VERSION": "2.0",
      "X-WR-CALNAME": "events",
      "PRODID": "-//Apple Inc.//iCal 4.0.4//EN",
      "X-APPLE-CALENDAR-COLOR": "#492BA1",
      "CALSCALE": "GREGORIAN",
      "VEVENT": [
        {
          "TRANSP": "OPAQUE",
          "DTEND": "20160601T020000Z",
          "DTSTAMP": "20160524T185925Z",
          "LOCATION": "Big Warehouse",
          "STATUS": "CONFIRMED",
          "SEQUENCE": "26533666",
          "CLASS": "PUBLIC",
          "SUMMARY": "Tickets OUT NOW!",
          "DTSTART": "20160531T210000Z",
          "CREATED": "20150722T163139Z"
        },
        {
          "TRANSP": "OPAQUE",
          "DTEND": "20160601T020000Z",
          "DTSTAMP": "20160524T185925Z",
          "LOCATION": "Small Warehouse",
          "STATUS": "CONFIRMED",
          "SEQUENCE": "26533666",
          "CLASS": "PUBLIC",
          "SUMMARY": "Tickets SOLD OUT!",
          "DTSTART": "20160531T210000Z",
          "CREATED": "20150722T163139Z"
        }
      ]
    }
  ]
}

PHP

$json = json_decode(file_get_contents('json/events.json'), true);
  foreach($json->VCALENDAR->VEVENT as $data) {
    echo $data->{'LOCATION'} . "\n";
}

I’m also looking for a way to convert the dates DSTART into something like 20 June 2016 ?

Any help thanks,
Barry

Can anybody help?

I’ve also tried the below, no errors and no data is showing:

foreach($json->VCALENDAR as $data)
{
  echo $data->VERSION . "\n";
  foreach($data->VEVENT as $values)
  {
       echo $values->LOCATION . "\n";
  }
}

Update:
Warning: Invalid argument supplied for foreach()
In both instances

Thanks,
Barry

Further update
The below now prints:

P 2 e - # G

Which is the first character from each VCALENDAR array value

foreach($json['VCALENDAR'] as $data)
{
  foreach($data as $yes) {
    echo $yes['LOCATION'] . "\n";
  }
}

Barry

json_decode() will turn the JSON into a multidimensional array, so properties can be accessed like e.g. $json["VCALENDAR"] (not with the -> notation). Also, the value of "VCALENDAR" is itself an array with only one element, so a particular "VEVENT" would be accessed like e.g. $json["VCALENDAR"][0]["VEVENT"]. You might iterate over the "VEVENT"s like so:

$json = json_decode(file_get_contents('json/events.json'), true);

foreach ($json["VCALENDAR"] as $vcalendar) {
    foreach ($vcalendar["VEVENT"] as $vevent) {
        echo $vevent["LOCATION"] . "\n";
    }
}

(Ah just noticed you already figured out the notation issue…) :-)

2 Likes

Hi Barry,

The first thing to keep in mind is that you’re passing true as the second argument to json_decode(), which causes JSON objects to be returned as associative arrays instead of PHP objects.

So, if you’re trying to get the LOCATION properties, your foreach is going to need to look like this:

foreach($json['VCALENDAR'][0]['VEVENT'] as $data) {
    echo $data['LOCATION'] . "\n";
}

Notice that VCALENDAR is an array (even though it only holds a single object in your example) so you need to use the index (0) to access the first element.

You can use PHP’s DateTime class to format the date:

$start = new DateTime($data['DTSTART']);
echo $start->format('j F Y');

The formatting codes to display the different parts of the date are here.

EDIT: ninja’d :wink:

2 Likes

Thanks [m3g4p0p], [fretburner] :grinning:

This is great!

Some good information here, will test, digest and respond shortly, couple of questions cheers.

Barry

Your example works perfect m3g4p0p :smile:

Likewise fretburner with your approach, I appreciate the two slightly different ways of doing things here, some great knowlegde, big thank you in advance.

After much googling… Though I’m wondering why, and when I would use one over the other?
$data->example vs $data['example']

I did think → was the new way of doing things.

Would things be better as a PHP object, or they work the same, not much benefit?

Cool, working good thanks for reference.

So generally speaking, now I have the json data available to me in a php array I can now spit out and organise this data exactly the same as I would with any db query. Is that correct? Meaning - it doesn’t matter where the data comes from, once inside the php array, everything works the same?

My updated code:

$json = json_decode(file_get_contents('events.json'), true);
foreach($json['VCALENDAR'] as $vcalendar)
{
  foreach($vcalendar['VEVENT'] as $vevent) {
    $start = new DateTime($vevent['DTSTART']);
      echo "<h3>" . $vevent['SUMMARY'] . "</h3><p>Location: " 
      . $vevent['LOCATION'] . "<br />When: " . $start->format('j F Y') . "</p>";
   }
 }

Also wondering how we could add a sort() into the mix?
Preferable sort by the date NOW onwards excluding past dates.

Update: When I print $vevent['DESCRIPTION '] all the data is full of \ and \n randomly added within the copy. Why is this? Is there a way to remove it?

Barry

Save yourself a great deal of grief and add

error_reporting(E_ALL); 

to the top of your php file. The first code you posted had obvious syntax errors.

Thanks ahundiak, note taken.
Good learning curve a suppose, things working quite good besides a few questions in my lastest post, cheers.

Barry

Hey Barry,

Some people prefer to access the data as an object rather than an associative array (i.e $vevent->SUMMARY rather than $vevent['SUMMARY']) but on the other hand this might prevent you from using some of PHP’s built-in array sorting/manipulation functions (depending on what you’re trying to do).

Yup, it’s just a normal collection of nested arrays at this point. You don’t need to worry about where the data came from.

I’d start by filtering the collection to include only the events that you want, using array_filter(). This takes an array and a filter function, and loops over the array, passing each element to the function. If the filter function returns true then that element is included in a new array which is returned by array_filter.

$today = new DateTime();

$current_events = array_filter($vcalendar['VEVENT'], function($event, $key) use ($today) {
    $event_start = new DateTime($vevent['DTSTART']);
    return $event_start >= $today;
}, ARRAY_FILTER_USE_BOTH);

Then I’d sort the resulting array, using usort. Note that this function doesn’t return a new array, it just sorts the array that you pass in as the first argument by passing pairs of elements to a sorting function that you pass as the second argument. This function should return 0 if the elements are equivalent, -1 if the first element comes before the second, and 1 if the first element should come after the second.

usort($current_events, function($a, $b) {
    $date_a = new DateTime($a['DTSTART']);
    $date_b = new DateTime($b['DTSTART']);

    if ($date_a == $date_b) return 0;
    return $date_a < $date_b ? -1 : 1;
});
1 Like

Big thank you @fretburner :sunglasses:

Some valuable information here which I’ll be able to use.

I have been working on a PHP importer and some MYSQL stuff over on databse section - https://www.sitepoint.com/community/t/querying-json-files-with-sql/227691

I’ve managed to import the JSON data into MYSQL which is making things a little easier right now to select and organize the data… This has taken up all the time past couple of nights :dizzy_face:

The good thing is… we now have options and more power to query the data by using JSON or by importing the JSON into MYSQL which will become very handy for different projects.

Will post back very soon to discuss things further about the above.

Cheers, Barry

Ok, I’ve decided to work with the mysql result which has turned out a little easier as mentioned. What you have suggested above is exactly what I need for my new snippet @fretburner VCALENDAR and VEVENT are no longer in use.

Just wondering how we can fit the ARRAY_FILTER and SORT into the new snippet below. Not sure if I need to create a new DateTime now - I have the row already formatted as shown below.

ORDER BY will be removed (somebody said PHP sorting is faster than SQL) is that correct?

$queryEvents = "
  SELECT ID
  , DTEND
  , DTSTAMP
  , LOCATION
  , DTSTART
  , SUMMARY
  FROM events_test
  
  ORDER BY DTSTART ASC";
$resultEvents = $mysqli->query($queryEvents);
$row_cnt = $resultEvents->num_rows;

$eventsArray = array();

/* fetch associative array */
while ($row = $resultEvents->fetch_assoc()) {
  $row['endTime'] = date('g:ia', strtotime($row['DTEND']));
  $row['fullDate'] = date('l jS F Y', strtotime($row['DTSTART']));
  $row['startTime'] = date('g:ia', strtotime($row['DTSTART']));
  
  $eventsArray[] = $row;
}

And further down the page I show the results:

foreach($eventsArray as $value){
  echo "<li><a href='event/{$value['ID']}'>
  {$value['SUMMARY']}<br>
  {$value['LOCATION']}<br>
  {$value['startTime']} - {$value['endTime']}</a></li>";
}

Some guidance cheers.


I’ll also be looking for a way to group these events into separate lists grouped under a date title, if maybe we could include this with the update somehow.

I came across array_chunk() though after further searching it seems a double foreach inside one another could be the right solution?

23rd June
event
event
event

24th June
event
event
event

Thanks, Barry :slight_smile:

Before I create a new thread with the same problem, if anybody could help with the above much appreciated. I realise this has become slightly off topic thanks.

I have tried the below though returning array(0). And not sure how to fit this into the foreach.

$today = new DateTime();
$current_events = array_filter($eventsArray, function($event) use ($today) {
  $event_start = $row['startTime'];
  return $event_start >= $today;
});
              
var_dump($current_events);

Barry

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.