AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Json parsen problem

Ein Thema von venice2 · begonnen am 14. Dez 2020 · letzter Beitrag vom 15. Dez 2020
Antwort Antwort
venice2
(Gast)

n/a Beiträge
 
#1

Json parsen problem

  Alt 14. Dez 2020, 23:34
Habe ein kleines Problem beim parsen meiner Json.

Code:
   "channels": [
      {
         "programs": [
            {
               "i_url": "http://images.zattic.com/cms/3f240530cf1a3bad8f63/format_480x360.jpg",
               "e": 1607986200,
               "g": [],
Auf channels kann ich zugreifen aber auf programs nicht.

Delphi-Quellcode:
function TZATJSON.GetJSONByNameOrIndex(const AData: Variant): TZATJSON;
begin
  case VarType(AData) and VarTypeMask of
    varString, varUString, varWord, varLongWord:
      if not FItems.TryGetValue(AData, Result) then //>>> Result ist nil weil ich nicht die korrekte Reihenfolge einhalte beim parsen. Nur wie? Wenn ich nicht an programs dran komme.
        raise EJSONUnknownFieldOrIndex.Create(format('Unknown field: %s', [AData]))
      else
        exit;
Delphi-Quellcode:
procedure TEpgDataList.FillList(aZatJson: TZATJSON);
var
  lZatJson: TZATJSON;
begin

  if assigned(aZatJson) then
  begin
    lZatJson := aZatJson.JSONByNameOrIndex['channels'];

    if assigned(lZatJson) and lZatJson.IsList then
    begin
      if lZatJson.ListItems.Count > 0 then
        addEpgData(lZatJson.ListItems[0]);
    end;
  end;
end;
Delphi-Quellcode:
procedure TEpgDataList.addEpgData(aZatJson: TZATJSON);
var
  entry: TEpgData;
  Epgloop: tEpgEntries;
  ltemp: TZATJSON;
  lEntrienames: tEpgEntryNames;
begin

  if assigned(aZatJson) then
  begin
    // Set up temporary Data
    entry := System.default(TEpgData);

    lEntrienames := EntryEpgNames;

    begin
      for Epgloop := Low(tEpgEntries) to High(tEpgEntries) do
        // Check if there is a Name.......
        if lEntrienames[Epgloop] <> 'then
        begin
          ltemp := aZatJson[lEntrienames[Epgloop]]; //>>>>>>
>> hier kracht es

wenn ich versuche 'i_url' anzusprechen ohne vorher programs initialisiert zu haben
programs will nicht nach channels und 'i_url' kann ich nicht aufrufen da es ein unterknoten von programs ist.
rufe ich programs auf ohne channels dann kracht es auch.
Also so!
lZatJson := aZatJson.JSONByNameOrIndex['programs'];
wo ist mein Fehler?

Wie kann ich also programs ansprechen damit es gefunden wird.

EDIT:
addiere ich jetzt programs zu den items die in die liste addiert werden sollen dann wird es korrekt gelesen.
Aber die untergeordneten Items werden wieder nicht erkannt.
Delphi-Quellcode:
  EntryEpgNames: TEpgEntryNames = ('programs', 'i_url', 'e', 'g', 'ry_u', 'i', 'sr_u', 'c',
    'r_e', 'rg_u', 'e_no', 's', 't', 'ser_e', 'c_ids', 'success');
grrr....

Geändert von venice2 (16. Dez 2020 um 16:26 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.540 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Json parsen problem

  Alt 15. Dez 2020, 06:49
channels ist ein JSON-Array bestehend aus JSON-Objekten. So ein JSON-Objekt verfügt wiederum um ein JSON-Array namens programs, das dann wieder aus JSON-Objekten mit den Eigenschaften i_url (String), e (String) und g (JSON-Array) besteht. Ich kenne die verwendete JSON-Klasse leider nicht, daher kann ich auch nicht sagen, wie man damit die vorhandene Struktur korrekt parst, aber vielleicht war das Aufdröseln schon hilfreich.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
venice2
(Gast)

n/a Beiträge
 
#3

AW: Json parsen problem

  Alt 15. Dez 2020, 06:52
channels ist ein JSON-Array bestehend aus JSON-Objekten. So ein JSON-Objekt verfügt wiederum um ein JSON-Array namens programs, das dann wieder aus JSON-Objekten mit den Eigenschaften i_url (String), e (String) und g (JSON-Array) besteht. Ich kenne die verwendete JSON-Klasse leider nicht, daher kann ich auch nicht sagen, wie man damit die vorhandene Struktur korrekt parst, aber vielleicht war das Aufdröseln schon hilfreich.
Die Klasse ist hier.. ich habe das Problem das ich nicht an programs dran komme.

Delphi-Quellcode:
{ ' UNIT uZatEPG.pas
  '--------------------------- uZatEPG -----------------------------
  ' Copyright © 2020 BrewIdeas@Emil Weiss, All Rights Reserved
  '
  ' Author(s) of this Unit: Emil Weiss
  '---------------------------------------------------------------------------- }


unit uZatEPG;

interface

{$REGION 'uses'}

uses
  Windows, Messages, SysUtils, StrUtils, VCL.Dialogs, Classes, UrlMon, ActiveX,
  uZatJson, uGlobal, CommCtrl, JsonDataObjects, Generics.Collections;
{$ENDREGION}

{$REGION 'Const/Type'}

type
  TEpgEntries = (i_url, e, g, ry_u, i, sr_u, c, r_e, rg_u, e_no, s, t,
    ser_e, c_ids, et, i_t, ts_id, id, tms_id, s_no, success);

  TEpgEntryNames = array [TEpgEntries] of string;

type
  TEpgData = record
    i_url: string;
    e: LongInt;
    g: string;
    ry_u: LongInt;
    i: string;
    sr_u: LongInt;
    c: string;
    r_e: BOOL;
    e_no: string;
    s: LongInt;
    t: string;
    ser_e: BOOL;
    c_ids: LongInt;
    et: string;
    i_t: string;
    ts_id: LongInt;
    id: LongInt;
    tms_id: string;
    s_no: LongInt;
    success: BOOL;
  end;

const
  EntryEpgNames: TEpgEntryNames = ('i_url', 'e', 'g', 'ry_u', 'i', 'sr_u', 'c',
    'r_e', 'rg_u', 'e_no', 's', 't', 'ser_e', 'c_ids', 'et', 'i_t','ts_id',
    'id', 'tms_id', 's_no', 'success');

{$ENDREGION}
{$REGION 'Class TEpgDataList'}

type
  TEpgDataList = class
  private
    EpgData: TList<TEpgData>;
    procedure addEpgData(aZatJson: TZATJSON);
    procedure fillfromJson(const aJsonString: string);
    procedure FillList(aZatJson: TZATJSON);
    function GetItems(index: integer): TEpgData;
  public
    constructor create(const aJsonString: string);
    destructor Destroy; override;
    function Count: integer;
    property Items[index: integer]: TEpgData read GetItems; default;
  end;
{$ENDREGION}

{$REGION 'Class TZatEpg'}
type
  TZatEpg = class
  private
    EpgDataList: TEpgDataList;
    function GetEpgInfoString(Path: string; Data: string; var Info: string): boolean;
    function FormatJSONStr(AString : string): string;
  public
    constructor create;
    destructor Destroy; override;
    procedure Filltitles(aitems: Tstrings);
    function GetEpgInfo(Path: string; Data: string): boolean;
    function Item(index: integer): TEpgData;
    function ValidData: boolean;
  end;
{$ENDREGION}

implementation

{$REGION 'TZatEpg'}

{ TZatEpg }

function TZatEpg.GetEpgInfo(Path: string; Data: string): boolean;
var
  lWideFileData: string;
begin
  Result := False;
  try
    if GetEpgInfoString(Path, Data, lWideFileData) then
    begin
      EpgDataList := TEpgDataList.create(lWideFileData);
    end;
    Result := ValidData;
  except
    on e: exception do
      ShowMessage(e.Message);
  end;
end;

function TZatEpg.GetEpgInfoString(Path: string; Data: string; var Info: string): boolean;
var
  TxtFile: string;
  dwBytes: DWORD;
  lstream: TFileStream;
  lutf8: UTF8String;
  List : TStringList;
begin

  Result := False;
  Info := '';

  if Path = 'then
    exit;

  TxtFile := Path + 'EPG_data.json';
  // get new Data from now
  if FileExists(TxtFile) then
    DeleteFile(TxtFile);

  List := TStringList.Create;
  try
    List.Append(Data);
    List.SaveToFile(TxtFile);
  finally
    List.Free;
  end;

  lstream := TFileStream.create(TxtFile, fmOpenReadWrite);
  try
    dwBytes := lstream.size;
    Setlength(lutf8, dwBytes);
    lstream.ReadBuffer(lutf8[1], dwBytes);
    Info := string(lutf8);
    // Format Json
    lutf8 := UTF8String(FormatJSONStr(string(lutf8)));
    lstream.Position := 0;
    lstream.WriteBuffer(lutf8[1], length(lutf8));
    Result := True;
  finally
    lstream.free;
  end;
end;

constructor TZatEpg.create;
begin

  inherited;

end;

destructor TZatEpg.Destroy;
begin

  if Assigned(EpgDataList) then
    FreeAndNil(EpgDataList);
  inherited;
end;

procedure TZatEpg.Filltitles(aitems: Tstrings);
//var
// I: integer;
begin

  aitems.clear;
// for I := 0 to EpgDataList.Count - 1 do
// aitems.add(EpgDataList[I].title);
end;

function TZatEpg.FormatJSONStr(AString: string): string;
var
  Obj: TJsonObject;
begin

  Obj := Obj.Parse(PWideChar(AString))as TJsonObject;
  result := Obj.ToJSON(False);
end;

function TZatEpg.Item(index: integer): TEpgData;
begin

  if ValidData then
    Result := EpgDataList[index];
end;

function TZatEpg.ValidData: boolean;
begin

  Result := assigned(EpgDataList) and (EpgDataList.Count > 0);
end;
{$ENDREGION}
{$REGION 'TEpgDataList'}

{ TEpgDataList }
constructor TEpgDataList.create(const aJsonString: string);
begin

  inherited create;
  EpgData := TList<TEpgData>.create;
  fillfromJson(aJsonString);
end;

destructor TEpgDataList.Destroy;
begin

  FreeAndNil(EpgData);
  inherited;
end;

procedure TEpgDataList.addEpgData(aZatJson: TZATJSON);
var
  entry: TEpgData;
  Epgloop: tEpgEntries;
  ltemp: TZATJSON;
  lEntrienames: tEpgEntryNames;
begin

  if assigned(aZatJson) then
  begin
    // Set up temporary Data
    entry := System.default(TEpgData);

    lEntrienames := EntryEpgNames;

    begin
      for Epgloop := Low(TEpgEntries) to High(TEpgEntries) do
        // Check if there is a Name.......
        if lEntrienames[Epgloop] <> 'then
        begin
          ltemp := aZatJson[lEntrienames[Epgloop]];

          if ltemp <> nil then
            case Epgloop of
              i_url: entry.i_url := ltemp.AsString;
              e: entry.e := ltemp.AsInteger;
              g: entry.g := ltemp.TArray;
              ry_u: entry.ry_u := ltemp.AsInteger;
              i: entry.i := ltemp.AsString;
              sr_u: entry.sr_u := ltemp.AsInteger;
              c: entry.c := ltemp.AsString;
              r_e: entry.r_e := ltemp.AsBoolean;
              e_no: entry.e_no := ltemp.AsString;
              s: entry.s := ltemp.AsInteger;
              t: entry.t := ltemp.AsString;
              ser_e: entry.ser_e := ltemp.AsBoolean;
              c_ids: entry.c_ids := ltemp.AsInteger;
              et: entry.et := ltemp.AsString;
              i_t: entry.i_t := ltemp.AsString;
              ts_id: entry.ts_id := ltemp.AsInteger;
              id: entry.id := ltemp.AsInteger;
              tms_id: entry.tms_id := ltemp.AsString;
              s_no: entry.s_no := ltemp.AsInteger;
            end;
        end;
    end;

    EpgData.add(entry);
  end;

end;

function TEpgDataList.Count: integer;
begin

  Result := EpgData.Count;
end;

procedure TEpgDataList.fillfromJson(const aJsonString: string);
Var
  lZatJson: TZATJSON;
begin

  lZatJson := TZATJSON.Parse(aJsonString);
  try
    if assigned(lZatJson) then
      FillList(lZatJson);

  finally
    lZatJson.free;
  end;
end;

procedure TEpgDataList.FillList(aZatJson: TZATJSON);
var
// I: integer;
  lZatJson: TZATJSON;
begin

  if assigned(aZatJson) then
  begin
    lZatJson := aZatJson.JSONByNameOrIndex['channels'];
    if assigned(lZatJson) and lZatJson.IsList then
    begin
      if lZatJson.ListItems.Count > 0 then
        addEpgData(lZatJson.ListItems[1]);
    end;
  end;
end;

function TEpgDataList.GetItems(index: integer): TEpgData;
begin

  Result := EpgData[index];
end;
{$ENDREGION}

end.
Danke für die Antwort.
Das ist die Funktion welche die Daten addiert

procedure TEpgDataList.FillList(aZatJson: TZATJSON); Und im Anhang die uZatJson.pas

Geändert von venice2 (16. Dez 2020 um 16:26 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.540 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Json parsen problem

  Alt 15. Dez 2020, 06:59
Das ist mir ehrlich gesagt zu schwierig auf die Schnelle nachzuvollziehen. Vielleicht hilft aber dieses Beispiel weiter (ich selbst benutze nur System.JSON, das gab es aber unter Delphi 2010 noch nicht IIRC): https://gist.github.com/fabriciocolo...010787d86b5c65
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
venice2
(Gast)

n/a Beiträge
 
#5

AW: Json parsen problem

  Alt 15. Dez 2020, 07:02
Das ist mir ehrlich gesagt zu schwierig auf die Schnelle nachzuvollziehen. Vielleicht hilft aber dieses Beispiel weiter (ich selbst benutze nur System.JSON, das gab es aber unter Delphi 2010 noch nicht IIRC): https://gist.github.com/fabriciocolo...010787d86b5c65
Hmmm.. schade.
Mit dem Code kann ich leider nichts anfangen ist ja quasi das gleiche.


Edit:
Habe es mal so versucht funktioniert leider nicht.
Delphi-Quellcode:
procedure TEpgDataList.FillList(aZatJson: TZATJSON);
var
// I: integer;
  channels: TZATJSON;
  programs: TZATJSON;
begin

  if assigned(aZatJson) then
  begin
    channels := aZatJson.JSONByNameOrIndex['channels'];
    if assigned(channels) and channels.IsList then // gibt mir den Count von 170 Sendern zurück
    begin
      programs := aZatJson.JSONByNameOrIndex['programs']; // hier kracht es
      if programs.ListItems.Count > 0 then
        addEpgData(programs.ListItems[1]);
    end;
  end;
end;

Geändert von venice2 (15. Dez 2020 um 07:13 Uhr)
  Mit Zitat antworten Zitat
Daniel
(Co-Admin)

Registriert seit: 30. Mai 2002
Ort: Hamburg
13.919 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Json parsen problem

  Alt 15. Dez 2020, 07:57
Und wenn Du nicht "aZatJson", sondern "channels" nach dem Element "programs" befragst? Immerhin ist "programs" ja auch ein direktes Unterelement davon.
programs := channels.JSONByNameOrIndex['programs']; .
Daniel R. Wolf
mit Grüßen aus Hamburg
  Mit Zitat antworten Zitat
venice2
(Gast)

n/a Beiträge
 
#7

AW: Json parsen problem

  Alt 15. Dez 2020, 08:07
Und wenn Du nicht "aZatJson", sondern "channels" nach dem Element "programs" befragst? Immerhin ist "programs" ja auch ein direktes Unterelement davon.
programs := channels.JSONByNameOrIndex['programs']; .
Das ist es ja warum geht es nicht.
so kann ich es nicht abfragen aber auf diese weise.

lZatJson := aZatJson.JSONByNameOrIndex['channels']; // ist ja schon die initialisierung von channels und funktioniert.

Dein Vorschlag wäre dann, falls ich dich richtig verstehe.

programs := lZatJson.JSONByNameOrIndex['programs'];
Danke für den Beitrag.

würde ich channels nehmen dann müsste ich channels als TZATJSON definieren.
habe es versucht schlägt aber ebenso fehl.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:19 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz