AGB  ·  Datenschutz  ·  Impressum  







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

JSON -> Database -> Auswertung ?

Ein Thema von bernhard_LA · begonnen am 1. Mai 2022 · letzter Beitrag vom 8. Mai 2022
Antwort Antwort
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#1

AW: JSON -> Database -> Auswertung ?

  Alt 3. Mai 2022, 06:08
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.
Gruß, Jo
  Mit Zitat antworten Zitat
bernhard_LA

Registriert seit: 8. Jun 2009
Ort: Bayern
1.138 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: JSON -> Database -> Auswertung ?

  Alt 6. Mai 2022, 13:21
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;

Geändert von bernhard_LA ( 6. Mai 2022 um 13:25 Uhr)
  Mit Zitat antworten Zitat
mytbo

Registriert seit: 8. Jan 2007
482 Beiträge
 
#3

AW: JSON -> Database -> Auswertung ?

  Alt 6. Mai 2022, 17:14
Eine dynamische Ermittlung alle Namen aus dem JSON File wäre besser (flexibler) für mich.
Die Funktion ist mit mORMot umgesetzt und nicht optimiert. Solange keine Millionen Datenobjekte vorliegen, sollte es schnell genug sein. Dafür lässt es sich sehr schnell umsetzen. Es werden folgende JSON Varianten verarbeitet: {"Value": "value1"} und [{"Value": "value1"},{"Value": "value2"}].
Delphi-Quellcode:
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;
Bis bald...
Thomas
  Mit Zitat antworten Zitat
mytbo

Registriert seit: 8. Jan 2007
482 Beiträge
 
#4

AW: JSON -> Database -> Auswertung ?

  Alt 8. Mai 2022, 14:47
Um dem Demonstrator einen nützlichen Aspekt zu geben und neben DocVariant eine weitere Klasse, die mORMot Text-Writer Klassen, vorzustellen, im folgendem ein funktionales Beispiel.
Berücksichtigte JSON Varianten:
  • {"Value": "value0"}
  • [{"Value": "value0"},{"Value": "value1"}]
  • [{"Value": "value0"},{},{"Value": "value1"}]
Disclaimer: Das Beispiel ist ein Proof of Concept, der Sourcecode ist weder getestet noch optimiert.
Delphi-Quellcode:
procedure ConvertJsonToCsv(const pmcJsonFileName: TFileName; const pmcCsvFileName: TFileName = ''; const pmcFilterFields: TRawUtf8DynArray = []);

  //-------- local functions ------------------------------------------

  procedure GetFieldNames(const pmcData: Variant; pmFieldNames: PRawUtf8DynArray; const pmcFilterFields: TRawUtf8DynArray);
  var
    fieldName: RawUtf8;
    docObject: PDocVariantData;
  begin
    SetLength(pmFieldNames^, 0);
    docObject := _Safe(pmcData);
    case docObject^.Kind of
      dvObject:
        ;
      dvArray:
        if docObject^.Count > 0 then
          docObject := _Safe(docObject^.Value[0])
        else
          Exit; //=> leeres Array
      else
        Exit; //=> dvUndefined
    end;

    for var i: Integer := 0 to High(docObject^.Names) do
    begin
      fieldName := docObject^.Names[i];
      if FindPropName(pmcFilterFields, fieldName) < 0 then
        AddRawUtf8(pmFieldNames^, fieldName, True, False);
    end;
  end;

  function VariantObjectToCsv(const pmcData: Variant; const pmcFieldNames: TRawUtf8DynArray): RawUtf8;
  var
    docObject: PDocVariantData;
    tmpBuffer: TTextWriterStackBuffer;
  begin
    docObject := _Safe(pmcData);
    if docObject^.Kind <> dvObject then Exit; //=>

    with TJsonWriter.CreateOwnedStream(tmpBuffer) do
    try
      for var i: Integer := 0 to High(pmcFieldNames) do
      begin
        AddVariant(docObject^.Value[pmcFieldNames[i]], twNone);
        AddComma;
      end;

      CancelLastComma;
      SetText(Result);
    finally
      Free;
    end;
  end;

  //-------- end local functions --------------------------------------

var
  jsonData: Variant;
  fieldNames: TRawUtf8DynArray;
  csvFileName: TFileName;
begin
  if not TDocVariantData(jsonData).InitJsonFromFile(pmcJsonFileName, JSON_OPTIONS_FAST_EXTENDED) then Exit; //=>

  GetFieldNames(jsonData, @fieldNames, pmcFilterFields);
  if Length(fieldNames) = 0 then Exit; //=>

  csvFileName := pmcCsvFileName;
  if csvFileName = 'then
    csvFileName := ChangeFileExt(pmcJsonFileName, '.csv');

  with TTextWriter.CreateOwnedFileStream(csvFileName) do
  try
    // Header schreiben
    AddString(RawUtf8ArrayToCsv(fieldNames));
    AddCR;

    // CSV Daten schreiben
    if TDocVariantData(jsonData).Kind = dvArray then
    begin
      for var i: Integer := 0 to TDocVariantData(jsonData).Count - 1 do
      begin
        AddString(VariantObjectToCsv(TDocVariantData(jsonData)[i], fieldNames));
        AddCR;
      end;
    end
    else
      AddString(VariantObjectToCsv(jsonData, fieldNames));

    FlushToStream;
  finally
    Free;
  end;
end;


var
  timer: TPrecisionTimer;
begin
  timer.Start;
  ConvertJsonToCsv('_listData.json', '', ['DasWillIchNicht', 'UndDasAuchNicht']);
  WriteLn(Format('Total time: %s', [timer.Stop]));
end;
Für 100K Objekte wird ca. 100ms benötigt. Für eine Variante, die tolerant gegenüber dem Eingangsformat ist, die mORMot Funktionen "out of the box" verwendet, gar kein schlechter Wert.

Bis bald...
Thomas
  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 17:10 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