Search code examples
jsondelphidelphi-xe6firedac

Delphi XE6 FireDAC - Export TFDQuery recordset to JSON


I'm using FireDAC in Delphi XE6 to query a database (Pervasive) through ODBC. I have a TFDQuery component which runs my SELECT query and returns the records. Once the query is complete I want to export the data in the recordset as JSON. I've tried using the following code :

fdacQuery.SaveToStream(myStream, sfJSON);

This creates JSON, but only for the table definition i.e. field names, data types, constraints etc. - there is no representation of the data. Is there another method I should be using to export just the recordset data as JSON? Is there another solution?


Solution

  • Try this on for size then. I did it for a utility I needed yesterday. It uses SuperObject. I left all field types in the code in case you want to add other special treatments or tweak any of those I put in. It's working for me on many random datasets right now.

    class procedure TTool.ExportDataSetToJson(DataSet: TDataSet; FileName: string; Append: boolean = false);
    const
      SData = 'data';
    var
      json : ISuperObject;
      item : ISuperObject;
      wasActive: boolean;
      fld : TField;
    begin
      json := SO;
      json.O[SData] := SA([]);
      wasActive := DataSet.Active;
      try
        DataSet.Active := true;
        DataSet.First;
        while not DataSet.Eof do
        begin
          item := SO;
          for fld in DataSet.Fields do
          begin
            case fld.DataType of
    //          ftUnknown: ;
              ftString,
              ftBlob,
              ftMemo,
              ftFmtMemo,
              ftBytes,
              ftVarBytes,
              ftFixedChar,
              ftFixedWideChar,
              ftWideMemo,
              ftByte,
              ftWideString: item.S[fld.FieldName] := fld.AsString;
              ftBoolean: item.B[fld.FieldName] := fld.AsBoolean;
              ftFloat,
              ftSingle,
              ftExtended,
              ftCurrency,
              ftFMTBcd,
              ftBCD: item.D[fld.FieldName] := fld.AsFloat;
              ftTime : item.S[fld.FieldName] := TimeToJson(fld.AsDateTime);
              ftDate,
              ftTimeStamp,
              ftOraTimeStamp,
              ftDateTime: item.S[fld.FieldName] := DateTimeToJson(fld.AsDateTime);
              ftSmallint,
              ftInteger,
              ftWord,
              ftAutoInc,
              ftLongWord,
              ftShortint,
              ftLargeInt: item.I[fld.FieldName] := fld.AsLargeInt;
    //          ftGraphic: ;
    //          ftParadoxOle: ;
    //          ftDBaseOle: ;
    //          ftTypedBinary: ;
    //          ftCursor: ;
    //          ftADT: ;
    //          ftArray: ;
    //          ftReference: ;
    //          ftDataSet: ;
    //          ftOraBlob: ;
    //          ftOraClob: ;
    //          ftVariant: ;
    //          ftInterface: ;
    //          ftIDispatch: ;
              ftGuid: item.S[fld.FieldName] := fld.AsString;
    //          ftOraInterval: ;
    //          ftConnection: ;
    //          ftParams: ;
    //          ftStream: ;
    //          ftTimeStampOffset: ;
    //          ftObject: ;
              else
                item.S[fld.FieldName] := fld.AsString;
            end;
          end;
          DataSet.Next;
          json.A[SData].Add(item);
        end;
        if Append then
          TFile.AppendAllText(FileName, json.AsJSon(true, true))
        else
          json.SaveTo(FileName, true, true);
      finally
        DataSet.Active := wasActive;
      end;
    
    end;