Comment faire un appel JSON à une url?

Je regarde l'API suivante:

Http://wiki.github.com/soundcloud/api/oembed-api

L'exemple qu'ils donnent est

Appel:

http://soundcloud.com/oembed?url=http%3A//soundcloud.com/forss/flickermood&format=json 

Réponse:

 { "html":"<object height=\"81\" ... ", "user":"Forss", "permalink":"http:\/\/soundcloud.com\/forss\/flickermood", "title":"Flickermood", "type":"rich", "provider_url":"http:\/\/soundcloud.com", "description":"From the Soulhack album...", "version":1.0, "user_permalink_url":"http:\/\/soundcloud.com\/forss", "height":81, "provider_name":"Soundcloud", "width":0 } 

Que dois-je faire pour obtenir cet objet JSON à partir d'une URL?

Il semble qu'ils offrent une option js pour le paramètre de format, qui retournera JSONP. Vous pouvez récupérer JSONP comme suit:

 function getJSONP(url, success) { var ud = '_' + +new Date, script = document.createElement('script'), head = document.getElementsByTagName('head')[0] || document.documentElement; window[ud] = function(data) { head.removeChild(script); success && success(data); }; script.src = url.replace('callback=?', 'callback=' + ud); head.appendChild(script); } getJSONP('http://soundcloud.com/oembed?url=http%3A//soundcloud.com/forss/flickermood&format=js&callback=?', function(data){ console.log(data); }); 

Une requête standard GET http devrait le faire. Ensuite, vous pouvez utiliser JSON.parse () pour l'intégrer à un objet json.

 function Get(yourUrl){ var Httpreq = new XMLHttpRequest(); // a new request Httpreq.open("GET",yourUrl,false); Httpreq.send(null); return Httpreq.responseText; } 

puis

 var json_obj = JSON.parse(Get(yourUrl)); console.log("this is the author name: "+json_obj.author_name); 

C'est essentiellement ça

Parce que l'URL ne se trouve pas sur le même domaine que votre site Web, vous devez utiliser JSONP.

Par exemple: (Dans jQuery):

 $.getJSON( 'http://soundcloud.com/oembed?url=http%3A//soundcloud.com/forss/flickermood&format=js&callback=?', function(data) { ... } ); 

Cela fonctionne en créant une <script> comme celle-ci:

 <script src="http://soundcloud.com/oembed?url=http%3A//soundcloud.com/forss/flickermood&format=js&callback=someFunction" type="text/javascript"></script> 

Leur serveur émet alors Javascript qui appelle someFunction avec les données à récupérer.
`SomeFunction est un rappel interne généré par jQuery qui appelle alors votre rappel.

La réponse de DickFeynman est une solution viable pour toute circonstance dans laquelle JQuery n'est pas un bon ajustement, ou n'est pas nécessaire. Comme l'indique ComFreek, cela nécessite de définir les en-têtes CORS sur le côté serveur. Si c'est votre service, et que vous vous occupez de la plus grande question de la sécurité, c'est tout à fait possible.

Voici une liste d'un service Flask, le réglage des en-têtes CORS, l'extraction de données à partir d'une base de données, la réponse à JSON et le bon fonctionnement de l'approche DickFeynman sur le côté client:

 #!/usr/bin/env python from __future__ import unicode_literals from flask import Flask, Response, jsonify, redirect, request, url_for from your_model import * import os try: import simplejson as json; except ImportError: import json try: from flask.ext.cors import * except: from flask_cors import * app = Flask(__name__) @app.before_request def before_request(): try: # Provided by an object in your_model app.session = SessionManager.connect() except: print "Database connection failed." @app.teardown_request def shutdown_session(exception=None): app.session.close() # A route with a CORS header, to enable your javascript client to access # JSON created from a database query. @app.route('/whatever-data/', methods=['GET', 'OPTIONS']) @cross_origin(headers=['Content-Type']) def json_data(): whatever_list = [] results_json = None try: # Use SQL Alchemy to select all Whatevers, WHERE size > 0. whatevers = app.session.query(Whatever).filter(Whatever.size > 0).all() if whatevers and len(whatevers) > 0: for whatever in whatevers: # Each whatever is able to return a serialized version of itself. # Refer to your_model. whatever_list.append(whatever.serialize()) # Convert a list to JSON. results_json = json.dumps(whatever_list) except SQLAlchemyError as e: print 'Error {0}'.format(e) exit(0) if len(whatevers) < 1 or not results_json: exit(0) else: # Because we used json.dumps(), rather than jsonify(), # we need to create a Flask Response object, here. return Response(response=str(results_json), mimetype='application/json') if __name__ == '__main__': #@NOTE Not suitable for production. As configured, # your Flask service is in debug mode and publicly accessible. app.run(debug=True, host='0.0.0.0', port=5001) # http://localhost:5001/ 

Your_model contient la méthode de sérialisation pour votre tout, ainsi que le gestionnaire de connexion à la base de données (qui pourrait résister à un peu de refactorisation, mais suffit de centraliser la création de sessions de base de données, dans des systèmes plus grands ou des architectures Model / View / Control). Cela arrive à utiliser postgreSQL, mais pourrait tout aussi bien utiliser n'importe quel magasin de données côté serveur:

 #!/usr/bin/env python # Filename: your_model.py import time import psycopg2 import psycopg2.pool import psycopg2.extras from psycopg2.extensions import adapt, register_adapter, AsIs from sqlalchemy import update from sqlalchemy.orm import * from sqlalchemy.exc import * from sqlalchemy.dialects import postgresql from sqlalchemy import Table, Column, Integer, ForeignKey from sqlalchemy.ext.declarative import declarative_base class SessionManager(object): @staticmethod def connect(): engine = create_engine('postgresql://id:passwd@localhost/mydatabase', echo = True) Session = sessionmaker(bind = engine, autoflush = True, expire_on_commit = False, autocommit = False) session = Session() return session @staticmethod def declareBase(): engine = create_engine('postgresql://id:passwd@localhost/mydatabase', echo=True) whatever_metadata = MetaData(engine, schema ='public') Base = declarative_base(metadata=whatever_metadata) return Base Base = SessionManager.declareBase() class Whatever(Base): """Create, supply information about, and manage the state of one or more whatever. """ __tablename__ = 'whatever' id = Column(Integer, primary_key=True) whatever_digest = Column(VARCHAR, unique=True) best_name = Column(VARCHAR, nullable = True) whatever_timestamp = Column(BigInteger, default = time.time()) whatever_raw = Column(Numeric(precision = 1000, scale = 0), default = 0.0) whatever_label = Column(postgresql.VARCHAR, nullable = True) size = Column(BigInteger, default = 0) def __init__(self, whatever_digest = '', best_name = '', whatever_timestamp = 0, whatever_raw = 0, whatever_label = '', size = 0): self.whatever_digest = whatever_digest self.best_name = best_name self.whatever_timestamp = whatever_timestamp self.whatever_raw = whatever_raw self.whatever_label = whatever_label # Serialize one way or another, just handle appropriately in the client. def serialize(self): return { 'best_name' :self.best_name, 'whatever_label':self.whatever_label, 'size' :self.size, } 

Rétrospectivement, je pourrais avoir sérialisé les objets que les listes, plutôt que le Python dict, qui aurait peut-être simplifié leur traitement dans le service Flask, et je pourrais avoir mieux séparé les problèmes dans la mise en œuvre du Flacon (l'appel de la base de données ne devrait probablement pas être Intégré au gestionnaire d'itinéraire), mais vous pouvez améliorer cela, une fois que vous avez une solution de travail dans votre propre environnement de développement.

De plus, je ne propose pas que les gens évitent JQuery. Mais, si JQuery n'est pas sur l'image, pour une raison ou une autre, cette approche semble être une alternative raisonnable.

Cela marche, en tout cas.

Voici ma mise en œuvre de l'approche de DickFeynman, dans le client:

 <script type="text/javascript"> var addr = "dev.yourserver.yourorg.tld" var port = "5001" function Get(whateverUrl){ var Httpreq = new XMLHttpRequest(); // a new request Httpreq.open("GET",whateverUrl,false); Httpreq.send(null); return Httpreq.responseText; } var whatever_list_obj = JSON.parse(Get("http://" + addr + ":" + port + "/whatever-data/")); whatever_qty = whatever_list_obj.length; for (var i = 0; i < whatever_qty; i++) { console.log(whatever_list_obj[i].best_name); } </script> 

Je ne vais pas énumérer la sortie de ma console, mais je regarde une longue liste de chaînes what.best_name.

Plus au point: le any_list_obj est disponible pour l'utilisation dans mon espace de noms javascript, pour tout ce qui me concerne, … ce qui pourrait inclure la génération de graphiques avec D3.js, le mappage avec OpenLayers ou CesiumJS, ou le calcul de certaines valeurs intermédiaires qui N'ont aucun besoin particulier de vivre dans mon DOM.

Vous faites une requête HTTP GET standard. Vous obtenez une réponse HTTP standard bog avec un type de contenu application / json et un document JSON en tant que corps. Vous analysez cela.

Puisque vous avez marqué ce «JavaScript» (je suppose que vous voulez dire «à partir d'une page Web dans un navigateur»), et je suppose que c'est un service tiers, vous êtes bloqué. Vous ne pouvez pas récupérer des données à partir d'URI distant dans JavaScript, à moins que des solutions de contournement explicites (comme JSONP) ne soient mises en place.

Oh, attendez, lisez la documentation que vous avez liée – JSONP est disponible, mais vous devez dire 'js' pas 'json' et spécifier un rappel: format = js & callback = foo

Ensuite, vous pouvez simplement définir la fonction de rappel:

 function foo(myData) { // do stuff with myData } 

Ensuite, chargez les données:

 var script = document.createElement('script'); script.type = 'text/javascript'; script.src = theUrlForTheApi; document.body.appendChild(script);