parsing JSONP $http.jsonp() response in angular.js
Asked Answered
D

8

114

I am using angular's $http.jsonp() request which is successfully returning json wrapped in a function:

var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts?callback=jsonp_callback";

$http.jsonp(url).
    success(function(data, status, headers, config) {
        //what do I do here?
    }).
    error(function(data, status, headers, config) {
        $scope.error = true;
    });

How to access/parse the returned function-wrapped-JSON?

Dotation answered 22/8, 2012 at 3:36 Comment(6)
With JSONP you don't "access/parse the returned function-wrapped-JSON." Your callback is called; it receives the JSON data as an argument.Teodorateodorico
I've tried doing something likeDotation
(sorry hit enter too soon above) At what point is my callback called? A code snippet would be really helpful. I've tried a number of different things at this point and am stumped.Dotation
The callback is called when the response comes back. Do you have a function named jsonp_callback? If not, there's your problem.Teodorateodorico
for now I've written a simple function to just return the first element of the json, function jsonp_callback(data) { return data.found; //should be 3 }Dotation
To people reading this question: Check out the solution to this problem that has been posted RIGHT AFTER the accepted answer.Qktp
O
302

UPDATE: since Angular 1.6

You can no longer use the JSON_CALLBACK string as a placeholder for specifying where the callback parameter value should go

You must now define the callback like so:

$http.jsonp('some/trusted/url', {jsonpCallbackParam: 'callback'})

Change/access/declare param via $http.defaults.jsonpCallbackParam, defaults to callback

Note: You must also make sure your URL is added to the trusted/whitelist:

$sceDelegateProvider.resourceUrlWhitelist

or explicitly trusted via:

$sce.trustAsResourceUrl(url)

success/error were deprecated.

The $http legacy promise methods success and error have been deprecated and will be removed in v1.6.0. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.

USE:

var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts"
var trustedUrl = $sce.trustAsResourceUrl(url);

$http.jsonp(trustedUrl, {jsonpCallbackParam: 'callback'})
    .then(function(data){
        console.log(data.found);
    });

Previous Answer: Angular 1.5.x and before

All you should have to do is change callback=jsonp_callback to callback=JSON_CALLBACK like so:

var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts?callback=JSON_CALLBACK";

And then your .success function should fire like you have it if the return was successful.

Doing it this way keeps you from having to dirty up the global space. This is documented in the AngularJS documentation here.

Updated Matt Ball's fiddle to use this method: http://jsfiddle.net/subhaze/a4Rc2/114/

Full example:

var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts?callback=JSON_CALLBACK";

$http.jsonp(url)
    .success(function(data){
        console.log(data.found);
    });
Oahu answered 15/11, 2012 at 15:13 Comment(10)
mine is returning a different callback: angular.callbacks._0 how should i fix this?Cabezon
@eaon21 do you have a fiddle example?Oahu
@eaon21 it's the desired behavior, angular substitutes JSON_CALLBACK to a dynamicly generated one, you don't have to pay attention to itClaymore
And how do you call Youtube api for example?Vandalism
It appears they have their own client side lib for interacting with the API. Any examples you have that can help narrow down what you're trying to do?Oahu
regarding the Angular 1.6 example - success is also deprecated.. you should use thenScrapple
@Scrapple thanks for the heads up! I've updated the answer to include this info.Oahu
@Oahu This is not working for me, I am using AngularJS 1.6, I tried all the above steps with AngularJS 1.5 also, can you have a look at this plunk. plnkr.co/edit/uOptrjxaFhT7xeaHX8YR?p=previewWaverly
Could just be that you're requesting http on a secured connection. Try https instead of http for your API endpoint if it supports it.Oahu
Hmm... just tried https myself and it doesn't appear to support https starlord.hackerearth.com/… so it probably wont work on any URL that's https. I also noticed on the non https side http://starlord.hackerearth.com/hackernews?callback=angular.callbacks._0 it's not sending back JSONP, it's just sending back JSONOahu
S
69

The MOST IMPORTANT THING I didn't understand for quite awhile is that the request MUST contain "callback=JSON_CALLBACK", because AngularJS modifies the request url, substituting a unique identifier for "JSON_CALLBACK". The server response must use the value of the 'callback' parameter instead of hard coding "JSON_CALLBACK":

JSON_CALLBACK(json_response);  // wrong!

Since I was writing my own PHP server script, I thought I knew what function name it wanted and didn't need to pass "callback=JSON_CALLBACK" in the request. Big mistake!

AngularJS replaces "JSON_CALLBACK" in the request with a unique function name (like "callback=angular.callbacks._0"), and the server response must return that value:

angular.callbacks._0(json_response);
Shortcircuit answered 15/10, 2013 at 2:11 Comment(1)
Is there any way we can change the name of the callback so that it works with hard-coded static json file.Doublebank
G
9

This was very helpful. Angular doesn't work exactly like JQuery. It has its own jsonp() method, which indeed requires "&callback=JSON_CALLBACK" at the end of the query string. Here's an example:

var librivoxSearch = angular.module('librivoxSearch', []);
librivoxSearch.controller('librivoxSearchController', function ($scope, $http) {
    $http.jsonp('http://librivox.org/api/feed/audiobooks/author/Melville?format=jsonp&callback=JSON_CALLBACK').success(function (data) {
        $scope.data = data;
    });
});

Then display or manipulate {{ data }} in your Angular template.

Goods answered 24/12, 2014 at 2:31 Comment(0)
T
4

This should work just fine for you, so long as the function jsonp_callback is visible in the global scope:

function jsonp_callback(data) {
    // returning from async callbacks is (generally) meaningless
    console.log(data.found);
}

var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts?callback=jsonp_callback";

$http.jsonp(url);

Full demo: http://jsfiddle.net/mattball/a4Rc2/ (disclaimer: I've never written any AngularJS code before)

Teodorateodorico answered 22/8, 2012 at 14:36 Comment(4)
That did it! It turns out the scope that I was messing up. Thank you!Dotation
This answer was not very helpful. It doesn't follow the scope of AngularJS.Cavalla
@Cavalla thanks for the feedback; unfortunately only the OP (akronymn) can switch the accepted answer, not me.Teodorateodorico
@DanieleBrugnara please see previous comments to this answer.Teodorateodorico
C
4

You still need to set callback in the params:

var params = {
  'a': b,
  'token_auth': TOKEN,
  'callback': 'functionName'
};
$sce.trustAsResourceUrl(url);

$http.jsonp(url, {
  params: params
});

Where 'functionName' is a stringified reference to globally defined function. You can define it outside of your angular script and then redefine it in your module.

Cabrilla answered 16/5, 2016 at 10:6 Comment(0)
D
2

For parsing do this-

   $http.jsonp(url).
    success(function(data, status, headers, config) {
    //what do I do here?
     $scope.data=data;
}).

Or you can use `$scope.data=JSON.Stringify(data);

In Angular template you can use it as

{{data}}
Dictograph answered 8/2, 2016 at 15:37 Comment(0)
C
0

for me the above solutions worked only once i added "format=jsonp" to the request parameters.

Christianechristiania answered 30/6, 2016 at 8:4 Comment(0)
M
0

I'm using angular 1.6.4 and answer provided by subhaze didn't work for me. I modified it a bit and then it worked - you have to use value returned by $sce.trustAsResourceUrl. Full code:

var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts"
url = $sce.trustAsResourceUrl(url);

$http.jsonp(url, {jsonpCallbackParam: 'callback'})
    .then(function(data){
        console.log(data.found);
    });
Magulac answered 11/5, 2017 at 6:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.