Einzelnen Beitrag anzeigen

Maekkelrajter

Registriert seit: 8. Mär 2017
Ort: Köln
157 Beiträge
 
Delphi 12 Athens
 
#14

AW: Problem bei JSON-Abfrage

  Alt 26. Sep 2020, 18:16
Nachdem das Ganze prinzipiell funktionierte, tauchte prompt die nächste Hürde auf. Die Spotify Web API limitiert nämlich die Zugriffe bei einer Playlist auf 100 Einträge. Ist die Liste länger, müssen weitere 'Seiten' des Paging-Objects nachgeladen und eingelesen werden. Die Frage war also, wie die weiteren Tracks dem Playlist-Objekt, soll heißen dem Array TPlaylist.Tracks.Items hinzugefügt werden können. Ich wollte nämlich keine zusätzliche 'externe' Liste für die Einträge anlegen, sondern nach Verlassen der Prozedur 'GetPlaylistTracks' sollte das Objekt 'Playlist' den kompletten Baum des von Spotify gelieferten Playlist-Objekts zur weiteren universellen Verwendung enthalten. Anderenfalls hätte man sich den ganzen Aufwand auch sparen können. Nach vielen Stunden mühsamer Recherche und viel Try & Error habe ich folgende Lösung gefunden:
Delphi-Quellcode:
Function TSpManager.SendRequest(accesspoint:string; offset: Integer = 0; Limit: Integer = 50):TJSONValue;
begin
  result:= NIL;
  If FAuthorized Then
  begin
    RESTRequest1.Params.ParameterByName('offset').Value:= offset.ToString;
    RESTRequest1.Params.ParameterByName('limit').Value:= limit.ToString;
    RESTRequest1.Resource:= AccessPoint;
    RestRequest1.Execute;
    result:= RestResponse1.JSONValue;
  end else If NoSpotifyAccessMsg = mrYes Then AuthorizespotifyAccess;
end;


function TSpManager.GetPlaylistTracks(var Playlist: TPlaylist; PlaylistID: string): Boolean; //komplette Playlist-Daten holen
var
  JValue,oitem: TJSONValue;
  oItems: TJSONArray;
  newitem: TPlaylisttrack;
  offs,nextpos,totalItems: Integer;
begin
  result := false;
  offs:= 0;
  JValue:= SendRequest('v1/playlists/' + PlaylistID);
  if JValue is TJSONObject then
  begin
    playlist := TJson.JsonToObject<TPlaylist>(TJSONObject(JValue));
    if playlist <> nil then
    begin
      totalItems:= playlist.Tracks.total;
      offs:= length(playlist.Tracks.Items);
      while offs < TotalItems do // nächste 'Seite' des Paging-Objects
      begin
        Jvalue:= SendRequest('v1/playlists/' + PlaylistID + '/tracks',offs,100);
        If JValue is TJSONObject Then
        begin
          oItems := TJSONArray(TJSONObject(JValue).GetValue('items'));
         // Erweitert das Array Playlist.Tracks.Items um oItems.count und liefert die bisherige Größe als Offset zurück:
          nextpos:= playlist.IncreaseItems(oitems.count);
          for oItem in oItems do
          begin
            newitem:= TJson.JsonToObject<TPlaylisttrack>(TJSONObject(oitem));
            playlist.SetItem(newitem,nextpos); // schreibt newitem in das Array
            inc(nextpos);
          end;
        end;
        inc(offs, oitems.Count);
      end;
    end;
  end;
  result:= playlist <> NIL;
end;
Das funktioniert auch perfekt, und sogar die Performance (incl. Ladevorgang) ist akzeptabel. Aber wie immer, wenn ich so etwas zusammen gefrickelt habe, kommt die Frage auf, ob diese Lösung wirklich 'State of The Art' ist und es nicht womöglich effizienter und/oder eleganter geht


Gruß LP
Miniaturansicht angehängter Grafiken
webapiscreenshot.jpg  
  Mit Zitat antworten Zitat