Как сделать JSON-вызов по URL? - PullRequest
40 голосов
/ 23 марта 2010

Я смотрю на следующий API:

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

Пример, который они приводят:

Вызов:

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

Ответ:

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

Что мне нужно сделать, чтобы получить этот объект JSON только из URL?

Ответы [ 5 ]

57 голосов
/ 23 марта 2010

Кажется, они предлагают параметр js для параметра формата, который будет возвращать JSONP.Вы можете получить JSONP следующим образом:

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);
});  
48 голосов
/ 01 апреля 2014

Стандартный HTTP GET запрос должен это сделать.Затем вы можете использовать JSON.parse (), чтобы превратить его в объект json.

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

затем

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

вот и все

11 голосов
/ 23 марта 2010

Поскольку URL не находится в том же домене, что и ваш веб-сайт, вам нужно использовать JSONP.

Например: (в jQuery):

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

Это работает путем созданиятег <script>, подобный этому:

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

Затем их сервер генерирует Javascript, который вызывает someFunction с данными для извлечения.
`someFunction - это внутренний обратный вызов, сгенерированный jQuery, который затем вызывает вашобратный вызов.

7 голосов
/ 16 июля 2014

Ответ Дика Фейнмана - это работоспособное решение для любых обстоятельств, в которых JQuery не подходит или не требуется иным образом.Как отмечает ComFreek, для этого необходимо установить заголовки CORS на стороне сервера.Если это ваша служба, и вы справляетесь с более широким вопросом безопасности, то это вполне осуществимо.

Вот список службы Flask, настройка заголовков CORS, получение данных из базы данных, ответ JSONи успешно работает с подходом ДикФейнмана на стороне клиента:

#!/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 содержит метод сериализации для всего, что угодно, а также менеджер соединений с базой данных (который может выдержать небольшой рефакторинг, но достаточно для централизации)создание сеансов базы данных в больших системах или архитектурах модель / представление / управление).Это происходит с использованием PostgreSQL, но с таким же успехом можно использовать любое хранилище данных на стороне сервера:

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

В ретроспективе я мог бы сериализовать любые объекты в виде списков, а не Python, который мог бы упроститьих обработка в службе Flask, и я мог бы лучше разделить проблемы в реализации Flask (вызов базы данных, вероятно, не должен быть встроен в обработчик маршрута), но вы можете улучшить это, как толькоу вас есть рабочее решение в вашей собственной среде разработки.

Кроме того, я не предлагаю людям избегать JQuery.Но если JQuery по той или иной причине отсутствует, этот подход кажется разумной альтернативой.

В любом случае это работает.

Вот моя реализация подхода Дика Фейнмана в клиенте:

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

Я не собираюсь перечислять вывод своей консоли, но я смотрю на длинный список строк what.best_name.

Еще к делу: what_list_obj доступен для использования в моем пространстве имен javascript, для независимо от , что я хочу сделать с ним, ... что может включать генерацию графики с D3.js,отображение с OpenLayers или CesiumJS, или вычисление некоторых промежуточных значений, которые не имеют особой необходимости жить в моем DOM.

4 голосов
/ 23 марта 2010

Вы делаете стандартный болван HTTP GET Request. Вы получаете стандартный HTTP-ответ HTTP с типом содержимого application / json и документом JSON в качестве тела. Затем вы анализируете это.

Поскольку вы пометили этот «JavaScript» (я предполагаю, что вы имеете в виду «с веб-страницы в браузере»), и я предполагаю, что это сторонний сервис, вы застряли. Вы не можете извлечь данные из удаленного URI в JavaScript, если не введены явные обходные пути (такие как JSONP).

Ой, подождите, читая документацию, на которую вы ссылались - JSONP доступен, но вы должны сказать «js», а не «json» и указать обратный вызов: format = js & callback = foo

Тогда вы можете просто определить функцию обратного вызова:

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

А затем загрузить данные:

var script = document.createElement('script');
script.type = 'text/javascript';
script.src = theUrlForTheApi;
document.body.appendChild(script);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...