0

I am testing an AngularJS website locally. I'm having problems parsing JSON data using $http.get from a local JSON file.

When I define the JSON in my controller, I have no problems. However, when I get the JSON from a file (data.json), the JSON format is different, according to the JavaScript console.

How come the JSON formats are different? Specifically, the $http.get retrieved JSON has numeric keys. Can I simply remove the numeric keys? Or is there something wrong with my JSON declaration/syntax? Below is a slew of additional information.

Here is how I define it in my controller:

$scope.customerReviews = [

        {
            'id': '0',
            'title': 'Outstanding Employee!',
            'text': 'bar foo bar foo',
            'image': '<img class="img-responsive img-hover" src="images/bob.jpg">',
            'href': '',
            'date': 'June 17, 2014',
            'author': 'john',
            'articleType': 'article',
            'neverSettle': 'partnering',
            'category': 'customerReviews'
        },
        {
            'id': '1',
            'title': 'hooray!',
            'text': 'congratulations',
            'image': '<img class="img-responsive img-hover" src="images/bob.png">',
            'href': '',
            'date': 'June 17, 2014',
            'author': 'sir charles',
            'articleType': 'article',
            'neverSettle': 'innovating',
            'category': 'customerReviews'
        },
        {
            'id': '2',
            'title': 'Outstanding Employee',
            'text': 'bar foo foo',
            'image': '<img class="img-responsive img-hover" src="images/bilbo.jpg">',
            'href': '',
            'date': 'June 17, 2014',
            'author': 'johnny',
            'articleType': 'article',
            'neverSettle': 'engaging',
            'category': 'customerReviews'
        },
        {
            'id': '3',
            'title': 'Thank you',
            'text': 'much thanks',
            'image': '<img class="img-responsive img-hover" src="images/x.jpg">',
            'href': '',
            'date': 'June 17, 2014',
            'author': 'The Graduate College',
            'articleType': 'article',
            'neverSettle': 'innovating',
            'category': 'customerReviews'
        }
  ];

When I copy paste from [ to ]; into the Chrome developer tools console, I get the following output:

better picture of controller-declared JSON console output

Like I said above, my current code prints my content perfectly. But if I try to get the JSON in an external file using $http.get, it doesn't print my content, and the JavaScript console shows a different JSON format.

Here is my $http.get code (in the controller):

  // http get json content
  $scope.customerReviews = [];
  $http.get("js/models/data.json").success(function(data){
      console.log("success!");
      $scope.customerReviews = data;
      console.log($scope.customerReviews);
      return $scope.customerReviews;
  });

Here is data.json. As you can see, this JSON file is different from how I define my controller. Specifically, the " and ' are switched to be JSON validation compliant. I ran this one through a JSON validator and it is formatted correctly. Also, when I copy paste this into the console, I get the first console output. Only when I do $http.get I get the "numeric keys" and my printing functions don't work.

[
    {
        "id ": "0 ",
        "title ": "Outstanding Employee! ",
        "text ": "too lazy to obfuscate all of my content",
        "image ": "<img class='img-responsive img-hover' src='images/GladisTolsa.jpg'> ",
        "href ": " ",
        "date ": "June 17, 2014 ",
        "author ": "Martha Castleberry ",
        "articleType ": "article ",
        "neverSettle ": "partnering ",
        "category ": "customerReviews "
    },
    {
        "id ": "1 ",
        "title ": "Facilities Help ",
        "text ": "too lazy to obfuscate all of my content",
        "image ": "<img class='img-responsive img-hover' src='images/FernandoLopez.png'> ",
        "href ": " ",
        "date ": "June 17, 2014 ",
        "author ": "Lucy Valenzuela ",
        "articleType ": "article ",
        "neverSettle ": "innovating ",
        "category ": "customerReviews "
    },
    {
        "id ": "2 ",
        "title ": "Outstanding Employee ",
        "text ": "too lazy to obfuscate all of my content",
        "image ": "<img class='img-responsive img-hover' src='images/MariaAlvarado.jpg'> ",
        "href ": " ",
        "date ": "June 17, 2014 ",
        "author ": "Martha Castleberry ",
        "articleType ": "article ",
        "neverSettle ": "engaging ",
        "category ": "customerReviews "
    },
    {
        "id ": "3 ",
        "title ": "Thank you ",
        "text ": "too lazy to obfuscate all of my content",
        "image ": "<img class='img-responsive img-hover' src='images/MovingServices.jpg'> ",
        "href ": " ",
        "date ": "June 17, 2014 ",
        "author ": "The Graduate College ",
        "articleType ": "article ",
        "neverSettle ": "innovating ",
        "category ": "customerReviews "
    }

]

So the $http.get request works. Here is the console output:

http.get console output

Phew. I apologize for the lengthiness of my question.

My Question: How come the seemingly equivalent JSONs are outputting different formats? Specifically, why does the $http.get retrieved JSON (the second one) have numeric keys? I need the second console output to have the same output as the first console output. Can I just remove the numeric keys? Or is there something wrong with my JSON declaration/syntax?

Any input is appreciated. Especially anything that could improve my AngularJS skills, and JSON knowledge. Thanks in advance.

EDIT: Thanks to everyone so far. Apparently those are array indexes written by Chrome developer tools, not numeric keys. I won't change my post title to avoid confusion for others. On request, here is how my printing works:

   <!-- ng repeat of Blog Preview Rows (reversed) -->
   <div ng-repeat="x in getCategory().slice().reverse() | limitTo:quantity " close="getCategory().splice(index, 1)">
        <previews></previews>
        <hr />
    </div>

getCategory() is a function that gets the querystring of the URL using regex. As stated before, this works when the JSON is declared in the controller. Perhaps getCategory() is ran after $http.get, therefore not printing anything? Also note that I simply reverse the ng-repeat.

Here is the <preview> directive:

.directive('previews', function () {
    return {
        restrict: 'AEC',
        replace: 'true',
        templateUrl: 'js/views/articleCollection.htm'
    };
});

articleCollection.htm:

<div class="row">

<div class="col-md-1 text-center">
        <p><span ng-bind-html="x.articleType"></span></p>
        <p><span ng-bind-html="x.neverSettle"></span></p>
    <p><span ng-bind-html="x.date"></span></p>
</div>
<div class="col-md-5">
    <a href="{{ x.href }}">
        <span ng-bind-html="x.image"></span>
    </a>
</div>
<div class="col-md-6">
    <h3>
        <a href="{{ x.href }}"><span ng-bind-html="x.title"></span></a>
    </h3>
    <p>
        by <span ng-bind-html="x.author"></span>
    </p>
    <p><span ng-bind-html="x.text"></span></p>
    <a class="btn btn-default" href="{{ x.href }}">Read More <i class="fa fa-angle-right"></i></a>
</div>
</div>

Thanks again. Let me know how I can further clarify my question. Also let me know how I can improve anything AngularJS related. So far, the journey has been a doozy.

chakeda
  • 1,551
  • 1
  • 18
  • 40
  • What numeric keys? The only numeric keys I see are the array index, which are only part of the developers tools presentation of an array. The output seems exactly the same. – Daniel Cardoso Jun 05 '15 at 20:07
  • It seems that way to me too. – Robert Moskal Jun 05 '15 at 20:10
  • I see, so those aren't numeric keys, but array indexes. The output does seem exactly the same, but my existing print functions (which use ng-repeat) don't work with the second one. Do the (lack of) array indexes have to do something with this? – chakeda Jun 05 '15 at 20:10
  • The output appears the same, an array with 4 objects. What do you have inside ng-repeat? It should be something like `ng-repeat="review in customerReviews track by $index"`. – Daniel Cardoso Jun 05 '15 at 20:13
  • @dcardoso, My ng-repeat is simple. Pretty much `ng-repeat="review in customerReviews`, but without `track by $index`. – chakeda Jun 05 '15 at 20:18
  • Provide a jsfiddle with a code sample of your problem. – Daniel Cardoso Jun 05 '15 at 20:21
  • @dcardoso, I also use a directive with a template in that ng-repeat. It will take me a while to construct the JSfiddle. In the meantime, I will post the code for my print functions. – chakeda Jun 05 '15 at 20:32

2 Answers2

1

Q: How come the seemingly equivalent JSONs are outputting different formats?

A: Because they are valid either way. See more info of JSON's syntax here

Q:Specifically, why does the $http.get retrieved JSON (the second one) have numeric keys?

A: I am guessing you are talking about the array position index at each array of objects. They make array easier to recognize. Of course, for viewing purpose in console.

Q: I need the second console output to have the same output as the first console output. Can I just remove the numeric keys?

A: Same as above. Google chrome output the 'numeric keys' are just for developers like us to easily recognize the position of array of object. You don't need then in your .json file.

Q: Or is there something wrong with my JSON declaration/syntax?

A: Nope. According to examples your provided, you are doing just fine. Keep up the good work!

EDIT

I've done some research, and, ahhhhhh I see your problem now.

Apparently reading JSON locally cause problem, so you need to modify a little bit.

See this:

AngularJS: factory $http.get JSON file

EDIT 2

Let me give it another go.

I personally have trouble relying on $scope, especially that I would not recommend to return a $scope in a function.

Try this:

app.factory("factoryExample", ['$http', function ($http) {
    return {
        Main: $http.get("js/models/data.json")
    }
}]);

//in controller
app.controller('MainController', ['$scope', 'factoryExample', function ($scope, factoryExample) {
    factoryExample.Main.success(function(data){
        $scope.customerReviews = data;
    });
}]);

As your post mentioned it seems like you are able to get json locally properly, my bad. After this code, your $scope.customerReview should be working!

EDIT3

Give your JSON a name, for your example:

{ "foo": 
    [
        {
            "id ": "0 ",
            "title ": "Outstanding Employee! ",
            "text ": "too lazy to obfuscate all of my content",
            "image ": "<img class='img-responsive img-hover' src='images/GladisTolsa.jpg'> ",
            "href ": " ",
            "date ": "June 17, 2014 ",
            "author ": "Martha Castleberry ",
            "articleType ": "article ",
            "neverSettle ": "partnering ",
            "category ": "customerReviews "
        },
        {
            "id ": "1 ",
            "title ": "Facilities Help ",
            "text ": "too lazy to obfuscate all of my content",
            "image ": "<img class='img-responsive img-hover' src='images/FernandoLopez.png'> ",
            "href ": " ",
            "date ": "June 17, 2014 ",
            "author ": "Lucy Valenzuela ",
            "articleType ": "article ",
            "neverSettle ": "innovating ",
            "category ": "customerReviews "
        },
        {
            "id ": "2 ",
            "title ": "Outstanding Employee ",
            "text ": "too lazy to obfuscate all of my content",
            "image ": "<img class='img-responsive img-hover' src='images/MariaAlvarado.jpg'> ",
            "href ": " ",
            "date ": "June 17, 2014 ",
            "author ": "Martha Castleberry ",
            "articleType ": "article ",
            "neverSettle ": "engaging ",
            "category ": "customerReviews "
        },
        {
            "id ": "3 ",
            "title ": "Thank you ",
            "text ": "too lazy to obfuscate all of my content",
            "image ": "<img class='img-responsive img-hover' src='images/MovingServices.jpg'> ",
            "href ": " ",
            "date ": "June 17, 2014 ",
            "author ": "The Graduate College ",
            "articleType ": "article ",
            "neverSettle ": "innovating ",
            "category ": "customerReviews "
        }

    ]
}

Then use:

<div ng-repeat="items in customerReviews.foo">{{items.id}}</div>

and so on.

Community
  • 1
  • 1
Taiwei Tuan
  • 430
  • 2
  • 12
  • Thank you for the clarifying points. My main question, is why do my print functions work with the first JSON, but not the second JSON, if they are both valid? Answering this question will resolve my post. – chakeda Jun 05 '15 at 20:21
  • Can you show us the code where you print them in your HTML? – Taiwei Tuan Jun 05 '15 at 20:30
  • According your link, I am possibly running into same-origin policy issues. Unfortunately, I cannot put this project on a web server today. I'll see if that fixes the problem. +1 for your effort. – chakeda Jun 05 '15 at 20:50
  • Updated again. See if it helps. – Taiwei Tuan Jun 05 '15 at 21:13
  • I get a `http://errors.angularjs.org/1.3.15/$injector/undef?p0=factoryExample`. I don't know much about factories so I'll look into debugging it. – chakeda Jun 05 '15 at 21:24
  • Updated. Again. Also would suggest to look into services ASAP if you are into AngularJS – Taiwei Tuan Jun 05 '15 at 21:29
  • I get a `Main is not defined`. – chakeda Jun 05 '15 at 21:52
  • Not a problem @DUANDAI, I greatly appreciate your input. Now there is no error, but I am back where I started. `console.log($scope.customerReviews);` reveals the second console output (with the array indexes) and no content printed out. I'm out of ideas here... – chakeda Jun 05 '15 at 22:07
  • Wow okay i have totally missed your problem. Anyways, Updated again! Its JSON! – Taiwei Tuan Jun 05 '15 at 22:40
0

Finally got the website on a web server, and the same code threw sce unsafe errors.

I just had to trust it as HTML before returning!

HTML-trustifying helper function:

  function arrayToHTML(data) {
      for (i = 0; i < data.length; i++) {
          data[i]["id"] = $sce.trustAsHtml(data[i]["id"]);
          data[i]["title"] = $sce.trustAsHtml(data[i]["title"]);
          data[i]["text"] = $sce.trustAsHtml(data[i]["text"]);
          data[i]["image"] = $sce.trustAsHtml(data[i]["image"]);
          data[i]["date"] = $sce.trustAsHtml(data[i]["date"]);
          data[i]["author"] = $sce.trustAsHtml(data[i]["author"]);
          data[i]["articleType"] = $sce.trustAsHtml(data[i]["articleType"]);
          data[i]["neverSettle"] = $sce.trustAsHtml(data[i]["neverSettle"]);
          data[i]["category"] = $sce.trustAsHtml(data[i]["category"]);
          data[i]["href"] = $sce.trustAsHtml(data[i]["href"]);
      }
  }

Working Code:

// http get json content
$scope.customerReviews = [];
$http.get("js/models/data.json").success(function(data){
    console.log("success!");
    $scope.customerReviews = data;
    console.log($scope.customerReviews);
    arrayToHTML($scope.customerReviews); // This fixed it!
    return $scope.customerReviews;
});
chakeda
  • 1,551
  • 1
  • 18
  • 40