Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

PHP

structure JSON by Key

I've got some php that is scraping a website and returning the data to arrays. I then want to take those arrays and output JSON to the page so that someone can make a JSON request to grab the info. I thought the best way to do this was use my arrays with key => value and then use json_encode to encode the arrays and thinking that json_encode would use the array keys to build the structure.
Well it did, to an extent. On my arrays like $array['courseCount'], it just printed the value for the key of 'courseCount' . I want it to print "courseCount": value,
On my arrays with more than two dimensions I got closer to what I want. For Example for when I encoded $array['course']['title'] I got "title": "the title I want". And when I used $array['course']['class']['date'] I got "date":"mm/dd/yyyy". I'm still missing the headers for each section though.
For example when it prints all the items in ['course']['class'] I want it to print out
"class": [
{
"date":"mm/dd/yyyy",
"location":"alaska",
}
]
etc etc

Enough talking , here's the parts of my code that matter:

$array['courseCount'] = $courseListQuery->length;
$jjson = json_encode($array['courseCount'],JSON_PRETTY_PRINT);

for ($x = 0; $x < $courseListQuery->length; $x++) {
$array['course']['title'] = $courseNameQuery->item($x)->nodeValue;
        $array['course']['outline'] = $courseOutlineQuery->item($x)->nodeValue;
        $array['course']['classCount'] = $classCountQuery->length;

$jjson .= json_encode($array['course'], JSON_PRETTY_PRINT);

for ($xa = 1; $xa < $classCountQuery->length + 1; $xa++) {

$array['course']['class']['date'] = trim($classDateQuery->item(0)->nodeValue);
            $array['course']['class']['stateEndTime'] = trim(preg_replace('/\s+/', ' ', $classTimeQuery->item(0)->nodeValue));
            $array['course']['class']['duration'] = trim(preg_replace('/\s+/', ' ', $classDurationQuery->item(0)->nodeValue));
            $array['course']['class']['location'] = trim(preg_replace('/\s+/', ' ', $classLocationQuery->item(0)->nodeValue));
            $array['course']['class']['type'] = $courseType;

$jjson .= json_encode($array['course']['class'],JSON_PRETTY_PRINT); 
}
}

echo "<pre>";
echo $jjson;
echo "</pre>";

sample of what I'm getting back:

2{
    "title": "InfoPath 2010 - Creating InfoPath Forms",
    "outline": "http:\/\/www.newhorizonssc.com\/LocalWeb\/popup\/ClassInfo.aspx?CourseKey=200004530&GroupID=402",
    "classCount": 6
}{
    "date": "5\/8\/2014",
    "stateEndTime": "8:30 AM - 4:30 PM",
    "duration": "1 Day(s)",
    "location": "Charleston, SC",
    "type": "ILT"
}{
    "date": "5\/8\/2014",
    "stateEndTime": "8:30 AM - 4:30 PM",
    "duration": "1 Day(s)",
    "location": "Columbia, SC",
    "type": "ILT"
}{
    "title": "InfoPath Designer 2010 with Sharepoint",
    "outline": "http:\/\/www.newhorizonssc.com\/LocalWeb\/popup\/ClassInfo.aspx?CourseKey=200004849&GroupID=402",
    "classCount": 1,
    "class": {
        "date": "6\/5\/2014",
        "stateEndTime": "8:30 AM - 4:30 PM",
        "duration": "1 Day(s)",
        "location": "Greenville, SC",
        "type": "ILT"
    }
}{
    "date": "5\/8\/2014",
    "stateEndTime": "8:30 AM - 4:30 PM",
    "duration": "1 Day(s)",
    "location": "Charleston, SC",
    "type": "ILT"
}

I did notice that it basically got it right when it cycled through the first for loop again. However then it repeats the whole process again for one class at the bottom which is really weird.

here's the format that I was asked to have it look like:

{ 
“courseCount” : ##,   
“course” : [
    {
            “title” : “XXXX”,
            “outlineURL” : “XXXX”,
             “classCount” : ##,
             “class” : [
                              {
                               “date” : “dddd”,
                               “startEndTime” : “XXXX”,
                               “duration” : “XXXX”,
                               “location” : “XXXX”,
                               “type” : “XXXX”
                             },
                              { …
                              }
                          ]
      },
      { …
      }
            ]
 }

this is my first time outputting a lot of json like this. Any help would be great! Thanks

2 Answers

$array = array();
$array['courseCount'] = $courseListQuery->length;
$array['courses'] = array();

for ($x = 0; $x < $courseListQuery->length; $x++) {
   $courseArray = array();

   $courseArray['title'] = $courseNameQuery->item($x)->nodeValue;
   $courseArray['outline'] = $courseOutlineQuery->item($x)->nodeValue;
   $courseArray['classCount'] = $classCountQuery->length;
   $courseArray['classes'] = array();

   for ($xa = 1; $xa < $classCountQuery->length + 1; $xa++) {
      $classesArray = array();

      $classesArray['date'] = trim($classDateQuery->item(0)->nodeValue);
      $classesArray['stateEndTime'] = trim(preg_replace('/\s+/', ' ', $classTimeQuery->item(0)->nodeValue));
      $classesArray['duration'] = trim(preg_replace('/\s+/', ' ', $classDurationQuery->item(0)->nodeValue));
      $classesArray['location'] = trim(preg_replace('/\s+/', ' ', $classLocationQuery->item(0)->nodeValue));
      $classesArray['type'] = $courseType;

      $courseArray['classes][] = $classesArray;
   }

$array['courses'][] = $courseArray;
}

$jjson = json_encode($array, JSON_PRETTY_PRINT);

echo "<pre>";
echo $jjson;
echo "</pre>";

Seems I am not quite sure how to post a block of code here but this is generally my idea.

man, that is so close. it's not printing out the info for each course, but it's perfect for all the classes. I'm going to work on it later on and I'll let you know. thanks.

oh and it's my sworn moderator responsibility to point out: how to post code to forum .... LOL

got it. changed the line $array['courses'][] = $courseArray['classes]; at the end to $array['courses'][] = $courseArray; and that printed the courses. now it outputs exactly. Thanks!

Sleepy me. Seems, I've made a syntax error too but that happens when you write code after midnight and without any IDE. Anyway, it's pleasure to help!

Just a simple question. Why do you encode one part of the array, then encode another part of it and then concatenate then? Have you tried by first building the whole array and then encode it?

Thanks for the reply. I did it this way because I'm going to have multiple arrays with same keys. For example if there are 5 class returned then I'm going to have 5 instances of $array['course']['class'] . They can't all occupy the same value, so I thought this was the best option. This way I create an $array['course']['class'] array, encode it, then create another $array['course']['class'], repeat. I'm all up for other ideas, I just need to end with specified structure.

Could you try without the loop, pretending there will be only one set of values, make the whole array and then encode it, just to check of you are getting the desired output that way? Coz if it works, then the problem will be clear and you could look for a more specific solution.

:/ same result:

one class no loops

2{
    "title": "InfoPath 2010 - Creating InfoPath Forms",
    "outline": "http:\/\/www.newhorizonssc.com\/LocalWeb\/popup\/ClassInfo.aspx?CourseKey=200004530&GroupID=402",
    "classCount": 6
}{
    "date": "5\/8\/2014",
    "stateEndTime": "8:30 AM - 4:30 PM",
    "duration": "1 Day(s)",
    "location": "Charleston, SC",
    "type": "ILT"
}

Okey, another idea. Let's say you have a global array called global. this global has two values: courseCount (int) and course (array). Then every value in the course array has 4 values: title (string), url (string), classCount (int) classes (array). Then every value in classes is also array with 5 values: date, start, duration, location, type. This way everything will be perfectly structured and you can make your global array without overwriting values and encode the whole stuff in the end. Hope you got my idea and it works.