【问题标题】:Consuming IMDB api results bad json使用 IMDB api 结果坏 json
【发布时间】:2019-07-24 16:44:12
【问题描述】:

我有一个使用 IMDB api 的简单程序,我得到了结果,但它显示为错误,因为结果不是结构化的 json。

MovieService.ts

export class MovieService {
  constructor(private http:HttpClient) { }
  getMovie(movie:string){
    return this.http.get(this.generateURL(movie));
  }
  private generateURL(movie:string){
    return "https://v2.sg.media-imdb.com/suggests/titles/"+movie.charAt(0)+"/"+movie+".json?callback=imdb$"+movie;
  }
}

addmovie.component.ts

   private _filterMovies(value: string) {
    this.movieService.getMovie(value).subscribe(
      movies => {
        console.log(movies);
        return movies;
      }
    );
  }

  ngOnInit() {
    this.addMovieForm.get('movie').valueChanges.subscribe(val => {
      this._filterMovies(val)
    });
  }

我遇到了类似的错误

响应是错误的 json。收到后如何格式化json?如何解决这个问题?任何线索都会有所帮助。

【问题讨论】:

标签: json angular typescript imdb


【解决方案1】:

结果不是JSON,而是JSONP。它本质上是向您返回一个试图执行指定回调方法的脚本。

你应该打电话给http.jsonp(url, "imbdIgnoresThisParam"),而不是http.get()

但是,according to this answercallback 查询字符串参数被 IMDB 忽略。答案建议动态创建预期的回调函数,其名称包含您要搜索的标题。在那个回调中,你可以做一些不同的事情。

  1. 使用闭包在MovieService 中调用/设置某些内容。这将导致您对 API 的调用引发错误,因为 Angular 框架的回调不会按预期调用。您可以忽略该错误。
  2. 尝试调用预期的 Angular 回调,ng_jsonp_callback_<idx>。这将防止 API 调用抛出,但它可能不可靠。回调名称是动态的,并随着每个jsonp() 调用而递增。您可以尝试在您的应用程序中跟踪jsonp() 调用的数量。当然,框架可能会改变并破坏这个解决方案。对getMovie() 的并发调用可能会中断,因为下一个调用可能会踩到窗口上的前一个回调。谨慎使用!

在 typescript 中,您的 getMovie() 函数和相关帮助程序可能如下所示:

private imdbData: any = null;
private jsonpIdx = 0;

private setImdb(json: any) {
    this.imdbData = json;
    // or do whatever you need with this
}

getMovie(movie:string) {
    // dynamically create the callback on the window.
    let funcName = `imdb$${movie}`;
    window[funcName] = (json: any) => {
        // use the closure
        this.setImdbData(json);

        // or try to call the callback that Angular is expecting.
        window[`ng_jsonp_callback_${this.jsonpIdx++}`](json);
    }

    // go get your data!
    let url = this.generateURL(movie)
    return this.http.jsonp(url, "ignored").subscribe((json) => {
        // this happens if you successfully trigger the angular callback
        console.log(json);
    }, (err) => {
        // this happens if the angular callback isn't called
        console.log(this.imdbData); // set in closure!
    });
}

为 Angular 4 编辑

对于Angular 4,您似乎需要将JsonpModuleHttpModule 一起导入。然后,您将注入jsonp,就像您将http 注入您的服务一样。对 IMDB 的调用变为 this.jsop.request(url).subscribe(...),您的动态回调名称也需要更改。

window[funcName] = (json: any) => {
    // or try to call the callback that Angular is expecting.
    window["__ng_jsonp__"][`__req${this.jsonpIdx++}`]["finished"](json);
}

我没有立即设置 Angular 5 或 6 项目,所以很难说这些版本中的回调是否有任何差异。

有点小技巧,但希望对您有所帮助!

【讨论】:

  • this.http.jsonp 不做任何事情。我认为它已被弃用。
  • @RanjithVaradan 您使用的是什么版本的Angular?我的示例适用于 Angular 7
  • 我使用的是最新版本 7.3.x
  • 我会检查 JsonpModule。并让您知道。
  • JsonpModule 在版本 7 中已弃用。相反,您应该在 HttpClient 中使用 jsonp() method
猜你喜欢
  • 2014-07-23
  • 2014-07-20
  • 2018-03-21
  • 1970-01-01
  • 2016-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多