restful example javascript json

javascript - example - ¿Cómo hacer una llamada JSON a una url?



yii web service (5)

Estoy mirando la siguiente API:

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

El ejemplo que dan es

Llamada:

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

Respuesta:

{ "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 }

¿Qué debo hacer para obtener este objeto JSON solo de una url?


Debido a que la URL no está en el mismo dominio que su sitio web, debe usar JSONP.

Por ejemplo: (en jQuery):

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

Esto funciona al crear una etiqueta <script> como esta:

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

Su servidor luego emite Javascript que llama a someFunction con los datos para recuperar.
`someFunction es una devolución de llamada interna generada por jQuery que luego llama a su devolución de llamada.


La respuesta de DickFeynman es una solución viable para cualquier circunstancia en la que JQuery no sea adecuado o no sea necesario. Como señala ComFreek, esto requiere configurar los encabezados CORS en el lado del servidor. Si es su servicio, y tiene un control sobre la gran cuestión de la seguridad, entonces eso es totalmente factible.

Aquí hay una lista de un servicio Flask, estableciendo los encabezados CORS, tomando datos de una base de datos, respondiendo con JSON, y trabajando felizmente con el enfoque de DickFeynman en el lado del cliente:

#!/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 contiene el método de serialización para lo que sea, además del administrador de conexión de la base de datos (que podría soportar un poco de refactorización, pero es suficiente para centralizar la creación de sesiones de base de datos, en sistemas más grandes o arquitecturas Modelo / Vista / Control). Esto pasa por usar postgreSQL, pero podría fácilmente usar cualquier almacén de datos del lado del servidor:

#!/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, }

En retrospectiva, podría haber serializado cualquier objeto como listas, en lugar de un dict de Python, lo que podría haber simplificado su procesamiento en el servicio Flask, y podría haber separado las preocupaciones en la implementación de Flask (la llamada a la base de datos probablemente no debería ser incorporado en el controlador de ruta), pero puede mejorarlo una vez que tenga una solución funcional en su propio entorno de desarrollo.

Además, no estoy sugiriendo que la gente evite JQuery. Pero, si JQuery no está en la imagen, por una razón u otra, este enfoque parece una alternativa razonable.

Funciona, en cualquier caso.

Aquí está mi implementación del enfoque de DickFeynman, en el cliente:

<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>

No voy a enumerar la salida de mi consola, pero estoy viendo una larga lista de cadenas de what.best_name.

Más al grano: Whatever_list_obj está disponible para su uso en mi espacio de nombres javascript, para lo que sea ​​que me interese hacer con él, ... que podría incluir generar gráficos con D3.js, mapear con OpenLayers o CesiumJS, o calcular algunos valores intermedios que no tengo ninguna necesidad particular de vivir en mi DOM.


Parece que ofrecen una opción js para el parámetro de formato, que devolverá JSONP. Puede recuperar JSONP de esta forma:

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); });


Una solicitud http GET estándar debería hacerlo. Luego puede usar JSON.parse () para convertirlo en un objeto json.

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

entonces

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

eso es básicamente


Usted hace una solicitud HTTP GET estándar de la turbera. Obtienes una Respuesta HTTP estándar de pantano con un tipo de contenido application / json y un documento JSON como cuerpo. A continuación, analiza esto.

Como ha etiquetado este ''JavaScript'' (supongo que quiere decir "desde una página web en un navegador"), y asumo que se trata de un servicio de terceros, está atascado. No puede obtener datos del URI remoto en JavaScript a menos que se implementen soluciones temporales explícitas (como JSONP).

Oh, espera, leyendo la documentación con la que vinculaste - JSONP está disponible, pero debes decir ''js'' no ''json'' y especificar una devolución de llamada: format = js & callback = foo

Entonces puedes simplemente definir la función de devolución de llamada:

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

Y luego carga los datos:

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