![]() |
Json parsen problem
Habe ein kleines Problem beim parsen meiner Json.
Code:
Auf channels kann ich zugreifen aber auf programs nicht.
"channels": [
{ "programs": [ { "i_url": "http://images.zattic.com/cms/3f240530cf1a3bad8f63/format_480x360.jpg", "e": 1607986200, "g": [],
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:
>> hier kracht es
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]]; //>>>>>> 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!
Delphi-Quellcode:
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:
grrr....
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'); |
AW: Json parsen problem
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.
|
AW: Json parsen problem
Zitat:
Delphi-Quellcode:
Danke für die Antwort.
{ ' 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. Das ist die Funktion welche die Daten addiert
Delphi-Quellcode:
Und im Anhang die uZatJson.pas
procedure TEpgDataList.FillList(aZatJson: TZATJSON);
|
AW: Json parsen problem
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):
![]() |
AW: Json parsen problem
Zitat:
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; |
AW: Json parsen problem
Und wenn Du nicht "aZatJson", sondern "channels" nach dem Element "programs" befragst? Immerhin ist "programs" ja auch ein direktes Unterelement davon.
Delphi-Quellcode:
.
programs := channels.JSONByNameOrIndex['programs'];
|
AW: Json parsen problem
Zitat:
so kann ich es nicht abfragen aber auf diese weise.
Delphi-Quellcode:
lZatJson := aZatJson.JSONByNameOrIndex['channels']; // ist ja schon die initialisierung von channels und funktioniert.
Dein Vorschlag wäre dann, falls ich dich richtig verstehe.
Delphi-Quellcode:
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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:45 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz