![]() |
JSON -> Database -> Auswertung ?
was will ich machen : eine möglichst flexible Auswertung über die Performance unserer Anwendung bekommen
Was machen wir bisher : wir sammeln Daten während der Ausführung unserer Anwendung , d.h. Ergebnisse, Berechnungszeiten, .... Wir haben eine ganz einfache Klasse definiert mit ~ 100 Attributen, könnten in Zukunft noch mehr werden :-)
Delphi-Quellcode:
Type LoggeAlles = class
Computername : String; Ausführungsdatum : TDatetime ; Ausführunsgzeit1 : TDatetime ; Ergebnis1 : Float; ..... ... end; JSONStr := TJson.ObjectToJsonString( LoggeAlles ); die Anwendung wird einige 100...1000 .... gestartet und ich bekomme ganz viele logfiles, diese lese ich wieder in eine Object-Liste ein und kann die Liste auch wieder als JSON Object speichern
Delphi-Quellcode:
/// /// load JSON /// JSONStr := TFile.ReadAllText(ListBox_Filenames.ListItems[i].text); NewLoggeAlles := TLoggeAlles.Create; NewLoggeAlles := TJson.JsonToObject<TNetlistsAnalysisresults>(JSONStr); LoggeAllesList.Add(NewLoggeAlles); Was ist jetzt mein Problem : ich suche eine möglichst elegante und flexible Option zur Auswertung meiner Daten , ich will eigentlich keinen Code für meine
Delphi-Quellcode:
schreiben :-)
Objectliste<TLoggerAlles)
Was würde ich machen : hier in der DP fragen wie ich meine JSON Daten am besten nach *.csv, *.xml oder *.xls bekomme, und dann mit Excel oder ??? auswerten Was suche ich hier , was wäre Euer Vorschlag für meine nächsten Schritte, gibt es hierfürm bereits Tools und code der mir weiterhelfen würde ? |
AW: JSON -> Database -> Auswertung ?
Für mich klingt das sehr nach Datenbankanwendung.
In 'ner DB eine Tabelle mit der gleichen Struktur, die in der Klasse abgebildet ist, anlegen. JSons in die Tabelle einfügen und dann alle Freiheiten der Auswertung per SQL genießen. Sortieren, gruppieren, summieren, Durchschnittswerte ermitteln, Maximum und/oder Minimum ermitteln, ... Als Code brauchst Du nur das Einlesen der JSons zu implementieren, wenn die DB das nicht schon kann. Oder eingebaute Funktionalitäten der DB nutzen. ![]() ![]() |
AW: JSON -> Database -> Auswertung ?
An so etwas hatte ich auch schon gedacht
Delphi-Quellcode:
TJSON.SavetoDB(.....) /// nur leider nicht gefunden :-(
wir verwenden MSSQL Server, dieser SQL Code erzeugt bei mir keine permanente Tabelle ( create table statement) und ich muss im select statement auch wieder alle Feldnamen angeben . Wir haben ja 100 + Feldnamen und die können sich permanent auch ändern, da will sehr flexibel bleiben
Delphi-Quellcode:
DECLARE @json NVARCHAR(MAX);
SET @json = N'[ {"id": 2, "info": {"name": "John", "surname": "Smith"}, "age": 25}, .... ]'; /// hier muss ich dann alle Feldnamen definieren ?? SELECT * FROM OPENJSON(@json) WITH ( id INT 'strict $.id', firstName NVARCHAR(50) '$.info.name', lastName NVARCHAR(50) '$.info.surname', age INT, dateOfBirth DATETIME2 '$.dob' ); und mit diesem code kann ich keine Querys platzieren oder ?
Delphi-Quellcode:
Declare @JSON varchar(max)
SELECT @JSON = BulkColumn FROM OPENROWSET (BULK 'E:\tempout.txt', SINGLE_CLOB) as j Select @JSON If (ISJSON(@JSON)=1) Print 'Valid JSON' |
AW: JSON -> Database -> Auswertung ?
Wenn Du "nichts" machen willst, würde ich einfach die Logfiles in Graphana kippen. (z.B. Du musst natürlich einen Server / Docker dafür aufsetzen)
Wenn Du mehr machen willst, also eine Vorverarbeitung, würde ich die Daten in Postgres importieren. Dort kannst Du damit nach Herzenslust rumtoben. Es gibt super JSON Funktionen und Operatoren, Objekt Zerlegung - Erzeugung. Vorgehen wäre bspw. ein JSON Logfile in eine BLOB Spalte (Typ bytea) schreiben, versehen mit ein paar generellen Merkmalen (Systemname, Datum, Maschine, ..) Du kannst alles was Du in der Importtabelle an "Randnotizen" in weiteren Spalten einträgst, bequem mit den JSON Daten mischen, auswerten, filtern, aggregieren. Ob das notwendig ist, sei dahin gestellt. Aber der Appetit kommt ja beim Essen. Import und Zwischenverarbeitung würde ich nur durch Scripting, Views machen. ![]() ![]() ![]() ![]() Wenn es wirklich viele Daten sind, kannst Du als Typ in Postgres JSONB nehmen. Das ist ein indizierbares Binärformat, funktionale Einschränkung verglichen mit JSON gibt es m.W. nicht. |
AW: JSON -> Database -> Auswertung ?
Statt die Klasse als JSon zu speichern, ihr eine Methode "gönnen", mit der sie von sich selbst eine Insert-Statement für die Datenbank generiert und dieses dann als Textdatei speichern.
Das könnte mit Hilfe von RTTI realisierbar sein. In dem Fall wären zusätzliche Attribute oder ggfls. deren Wegfall transperant für die Exportroutine, so dass sie nur einmalig erstellt werden muss und eine Anpassung dieser Routine bei Änderungen an der Klasse nicht erforderlich werden. Die Struktur der Datenbanktabelle müsste dann aber halt (bei Änderungen an der Klasse) händisch synchron zur Klasse gehalten werden. |
AW: JSON -> Database -> Auswertung ?
Zitat:
Könntest du ein paar solcher Datensätze als JSON zum Testen bzw. als Beispiel hier bereit stellen? |
AW: JSON -> Database -> Auswertung ?
Daten kann ich leider hier nicht veröffentlichen.
Die Daten entstehen durch die Benutzung der Software aber vor allem auch durch Testcases. (wir verwendenden MSBuild und Jenkins). Ziel ist dabei die Optimierung von Algorithmen. Für mich der Vergleich der Ergebnisse mit verschiedenen testdaten als auch mit verschiedenen Code- Varianten hilfreich.
Delphi-Quellcode:
Type LoggeAlles = class
private FComputername : String; public Ausführungsdatum : TDatetime ; Ausführunsgzeit1 : TDatetime ; Ergebnis1 : Float; ..... ... /// NEU : für alle Felder die ich auslesen will werden jetzt properties eingeführt property Computername : String read FComputername write FComputername; end; /// diese Funktion liefert mir die Namen alles Prop. meiner Klasse als Stringliste procedure CheckProperties(Obj: TObject; sLst : TStringlist); var ctx: TRttiContext; objType: TRttiType; Prop: TRttiProperty; begin ctx := TRttiContext.Create; objType := ctx.GetType(Obj.ClassInfo); for Prop in objType.GetProperties do sLst.Add(Prop.Name); end; Aktuell suche ich eine Optionen bestimmte Feldnamen in eine *.csv Datei ausgewählt über die property & RTTI zu schreiben
Delphi-Quellcode:
Warum bekomme ich eine AV im Code oben/// Lösung : Für alle ausgewählten Properties meiner Klasse den Wert des /// Feldes in eine Memo , *.csv oder .... schreiben /// for j := 0 to LoggeAllesList.Count - 1 do begin aLoggeAlles := LoggeAllesList.Items[j]; ctx := TRttiContext.Create; objType := ctx.GetType(aLoggeAlles); /// ----- >>>> AV ??? for i := 0 to sLst.Count - 1 do begin FField := objType.GetField(sLst[i]); Memo.Lines.Add( FField.ToString ); end; end; |
AW: JSON -> Database -> Auswertung ?
Wenn es um die Daten / DDL Strukturen geht, wie wär es mit Key Value.
JSON ist es ja egal, was Du wie lang da rein schreibst, aber SQL eben nicht. Keine Dynamik, außer mit speziellen SP, geht glaub ich auch in MSSQL, aber ist eine eigene Baustelle, Daten klassisch in JSON, die 1:1 in eine Table als Datensatz überführt werden können. [{"id":1,"name":"January"},{"id":2,"name":"February "}] [{"id":1,"name":"January"},{"id":2,"name":"February "}] Als KV [ {"id":1}, {"name":"January"}, {"id":2}, {"name":"February"}], [ {"id":1}, {"name":"January"}, {"id":2}, {"name":"February"}] und natürlich egal, welche Attribute: [ {"bigid":1}, {"Kontextname":"January"}, {"id":2}, {"anderername":"February"} {"Zusatzattribut":"February"} ] Hast Du eine konkrete Vorstellung, welche Attribute es sein sollen und wie hoch sagen wir die Deckungsgleichheit bei verschiedenen Tests ist? Spaß macht SQL natürlich nur mit festen Strukturen. Man kann aber jedes JSON in eine feste Struktur überführen. Variante, wenn man 100 Attribute hat, und 70 davon sind sowieso fest, braucht man kein JSON dafür, nur halt ein Feld für "JSON Reste", den variablen Teil. JSON wäre m.E. eine Lösung für die Strecke: Ich mache jetzt schon mal Tests, weiß aber noch nicht, was mich eigentlich interessiert (weil ich das erst bei der Auswertung rausfinde) Je länger die Tests laufen, desto fester wird die Definition der Daten, die wichtig und demnach statisch ermittelt und analysiert werden. Alles was fest ist, kommt in eine Tabelle, der Rest weiter JSON. Du kannst also z.B. CSV loggen mit 70 festen Spalten und einer JSON Spalte, wo der ganze Kram drin steht, der noch unspezifisch ist. Und entsprechend der CSV auch eine Tabelle haben, die es genauso importiert. |
AW: JSON -> Database -> Auswertung ?
Update :
Über RTTI besorge ich mir die Namen aller Properies meiner Klasse als Stringliste. Diese Stringliste übergebe ich dann an meine JSON Auswerte + CSV File schreibe funktion. Eine dynamische Ermittlung alle Namen aus dem JSON File wäre besser (flexibler) für mich. Wer ähnliche Ausfgaben hat kann hier gerne auch was posten :-) , aktuell bin ich einen Schritt weiter.
Delphi-Quellcode:
procedure TMyForm.ShowJSONarraylistUsingProperties (sLst: TStringlist; csvfilename: String); var jsArr: TJSONArray; originalObject: TJsonObject; jsPair: TJsonPair; jsObj: TJsonObject; JsVAl: TJsonValue; i: Integer; Singleline: string; HeaderCSV: string; DataCSV: string; csvfile: TStringlist; begin csvfile := TStringlist.Create; try JsVAl := TJsonObject.ParseJSONValue(FJSONStr); // value as object originalObject := JsVAl as TJsonObject; // get pair, wich contains Array of objects jsPair := originalObject.Get('listHelper'); // pair value as array jsArr := jsPair.jsonValue as TJSONArray; // writeln('array size: ', jsArr.Size); // enumerate objects in array for i := 0 to jsArr.Size - 1 do begin LogMemo.Lines.Add('element ' + IntTostr(i)); // i-th object jsObj := jsArr.Get(i) as TJsonObject; HeaderCSV := ''; DataCSV :=''; // enumerate object fields for jsPair in jsObj do begin if (sLst.IndexOf(jsPair.JsonString.Value) > 0) then begin Singleline := Singleline + ' [' + jsPair.JsonString.Value + ' : ' + jsPair.jsonValue.Value + '] '; HeaderCSV := HeaderCSV + jsPair.JsonString.Value+ '; '; DataCSV := DataCSV + jsPair.jsonValue.Value + '; '; end; end; if i = 0 then csvfile.Add(HeaderCSV); csvfile.Add(DataCSV); LogMemo.Lines.Add(Singleline); end; finally csvfile.SaveToFile(csvfilename); csvfile.Free; end; end; |
AW: JSON -> Database -> Auswertung ?
Zitat:
Delphi-Quellcode:
Bis bald...
uses
mormot.core.base, mormot.core.data, mormot.core.text, mormot.core.json, mormot.core.unicode, mormot.core.variants, mormot.core.os; procedure GetFieldNames(const pmcData: Variant; pmpFieldNames: PRawUtf8DynArray; const pmcFilterFields: array of RawUtf8); var i: Integer; run: PDocVariantData; fieldName: RawUtf8; begin SetLength(pmpFieldNames^, 0); case _Safe(pmcData)^.Kind of dvObject: run := _Safe(pmcData); dvArray: run := _Safe(TDocVariantData(pmcData).Value[0]); else Exit; //=> dvUndefined end; for i := 0 to High(run.Names) do begin fieldName := run.Names[i]; if FindPropName(pmcFilterFields, fieldName) < 0 then AddRawUtf8(pmpFieldNames^, fieldName, True, False); end; end; var i, n: Integer; value: Variant; jsonData: Variant; jsonDataCount: Integer; fieldNames: TRawUtf8DynArray; begin if not TDocVariantData(jsonData).InitJsonFromFile('JsonData.json', JSON_OPTIONS_FAST_EXTENDED) then Exit; //=> GetFieldNames(jsonData, @fieldNames, ['DasWillIchNicht']); if Length(fieldNames) = 0 then Exit; //=> if TDocVariantData(jsonData).Kind = dvArray then jsonDataCount := TDocVariantData(jsonData).Count else jsonDataCount := 1; for i := 0 to jsonDataCount - 1 do begin for n := 0 to High(fieldNames) do begin if jsonDataCount = 1 then value := TDocVariantData(jsonData).Value[fieldNames[n]] else value := _Safe(TDocVariantData(jsonData)[i])^.Value[fieldNames[n]]; WriteLn(value); end; end; end; Thomas |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:09 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