Использование API IMDB приводит к плохому JSON - PullRequest
0 голосов
/ 03 марта 2019

У меня есть простая программа, которая использует 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)
    });
  }

Я получаю сообщение об ошибке типа

enter image description here

Ответ плохой JSON,Как я могу отформатировать JSON при получении?Как это решить?Любые выводы будут полезны.

1 Ответ

0 голосов
/ 03 марта 2019

Результат не JSON, а JSONP .По сути, он возвращает вам скрипт, который пытается выполнить указанный метод обратного вызова.

Вместо http.get() вы должны вызвать http.jsonp(url, "imbdIgnoresThisParam").

Однако согласно этому ответу, параметр строки запроса callback игнорируется IMDB.Ответ предлагает динамически создать ожидаемую функцию обратного вызова, имя которой содержит заголовок, который вы ищете.В этом обратном вызове вы могли бы сделать несколько разных вещей.

  1. Используйте замыкание для вызова / установки чего-либо в вашем MovieService.Это приведет к тому, что ваш вызов API вызовет ошибку, поскольку обратный вызов платформы Angular не будет вызываться, как ожидалось.Вы можете игнорировать ошибку.
  2. Попробуйте вызвать ожидаемый обратный вызов Angular, ng_jsonp_callback_<idx>.Это предотвратит вызов API, но это может быть ненадежно.Имя обратного вызова является динамическим и увеличивается с каждым jsonp() вызовом.Вы можете попытаться отследить количество вызовов jsonp() в своем приложении.И, конечно, рамки могут изменить и сломать это решение.Одновременные вызовы getMovie() могут прерваться, так как следующий вызов может перейти к предыдущему обратному вызову в окне.Используйте с осторожностью!

В машинописном тексте ваша функция 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 похоже, что вам нужно будет импортировать JsonpModule вместе с HttpModule.Затем вы вводите 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, поэтому сложно сказать, есть лилюбые различия с обратным вызовом в этих версиях.

Вроде хак, но надеюсь, что это поможет!

...