Delphi FDQuery到Json

时间:2017-05-26 16:46:18

标签: json delphi delphi-xe delphi-10.1-berlin firedac

我正在尝试将我的Sqlite查询的结果转换为Json, 使用与我通过php远程绑定到Sql Server时使用的相同过程。

代码有效,但你认为这是一个更好的解决方案吗?

有人这样做吗?

function TLogin.RetornaRegistros(query:String): String;
var
  FDQuery : TFDQuery;
  field_name,nomeDaColuna,valorDaColuna : String;
  I: Integer;
begin
    FDQuery := TFDQuery.Create(nil);
    try
      FDQuery.Connection := FDConnection1;
      FDQuery.SQL.Text := query;
      FDQuery.Active := True;
      FDQuery.First;

      result := '[';
      while (not FDQuery.EOF) do
      begin

        result := result+'{';
        for I := 0 to FDQuery.FieldDefs.Count-1 do
        begin
          nomeDaColuna  := FDQuery.FieldDefs[I].Name;
          valorDaColuna := FDQuery.FieldByName(nomeDaColuna).AsString;
          result := result+'"'+nomeDaColuna+'":"'+valorDaColuna+'",';
        end;
        Delete(result, Length(Result), 1);
        result := result+'},';

        FDQuery.Next;
      end;
      FDQuery.Refresh;

      Delete(result, Length(Result), 1);
      result := result+']';

    finally
      FDQuery.Free;
    end;
end;

5 个答案:

答案 0 :(得分:2)

我刚修改了下面的第一个答案,以编译不同类型的字段,以适当的json格式转换数字,日期和布尔值。 我评论了我没有测试的类型。 看

使用{...} System.JSON;

Var    
FDQuery : TFDQuery;
field_name,Collumnname,CollumnValue : String;
I: Integer;

LJSONObject:TJsonObject;
begin
    FDQuery := TFDQuery.Create(nil);
    try
      FDQuery.Connection := FDConnection1;
      FDQuery.SQL.Text := query;
      FDQuery.Active := True;
      FdQuery.BeginBatch;//Don't update external references until EndBatch;
      FDQuery.First;
      LJSONObject:= TJSONObject.Create;
      while (not FDQuery.EOF) do
      begin
            for I := 0 to FDQuery.FieldDefs.Count-1 do
            begin
              CollumnName  := FDQuery.FieldDefs[I].Name;
              Case FDQuery.FieldDefs[I].Datatype of
                  ftBoolean: 
                    IF FDQuery.FieldDefs[I].Value=True then   LJSONObject.AddPair(TJSONPair.Create(TJSONString.Create( CollumnName),TJSONTrue.Create)) else 
                      LJSONObject.AddPair(TJSONPair.Create(TJSONString.Create( CollumnName),TJSONFalse.Create)); 
                  ftInteger,ftFloat{,ftSmallint,ftWord,ftCurrency} :
                    LJSONObject.AddPair(TJSONPair.Create(TJSONString.Create( CollumnName),TJSONNumber.Create(FDQuery.FieldDefs[I].value)));   
                  ftDate,ftDatetime,ftTime:
                   LJSONObject.AddPair(TJSONPair.Create(TJSONString.Create( CollumnName),TJSONString.Create(FDQuery.FieldDefs[I].AsString)));
//or TJSONString.Create(formatDateTime('dd/mm/yyyy',FDQuery.FieldDefs[I].Value));
                  else LJSONObject.AddPair(TJSONPair.Create(TJSONString.Create( CollumnName),TJSONString.Create(FDQuery.FieldDefs[I].AsString)));
              End;
            FDQuery.Next;
          end;
         FdQuery.EndBatch;
        finally 
          FDQuery.Free;
          Showmessage(LJSonObject.ToString);
        end;
    end;

有关dataset.DataType http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/DB_TFieldType.html

的更多信息

有关JSONTypes https://community.embarcadero.com/blogs/entry/json-types-for-server-methods-in-datasnap-2010-4

的更多信息

答案 1 :(得分:1)

这不是一个好方法。我真的建议至少考虑树选项:

  1. 使用System.JSON单元的强大功能。
  2. 使用{...} System.JSON;

    Var    
    FDQuery : TFDQuery;
    field_name,Collumnname,CollumnValue : String;
    I: Integer;
    
    LJSONObject:TJsonObject;
    begin
        FDQuery := TFDQuery.Create(nil);
        try
          FDQuery.Connection := FDConnection1;
          FDQuery.SQL.Text := query;
          FDQuery.Active := True;
          FdQuery.BeginBatch;//Don't update external references until EndBatch;
          FDQuery.First;
          LJSONObject:= TJSONObject.Create;
          while (not FDQuery.EOF) do
          begin
                for I := 0 to FDQuery.FieldDefs.Count-1 do
                begin
                  CollumnName  := FDQuery.FieldDefs[I].Name;
                  CollumnValue := FDQuery.FieldByName(CollumnName).AsString;
                  LJSONObject.AddPair(TJSONPair.Create(TJSONString.Create( CollumnName),TJSONString.Create(CollumnValue)));
                FDQuery.Next;
              end;
              //FDQuery.Refresh; that's wrong
             FdQuery.EndBatch;
            finally 
              FDQuery.Free;
              Showmessage(LJSonObject.ToString);
            end;
        end;
    

    https://www.youtube.com/watch?v=MLoeLpII9IE&t=715s

    1. 第二种方法,使用FDMemTable.SaveToStream; 同样适用于FDMemTable.SaveToFile; 在数据模块上放置TFDMemTable(或者也可以形成)。

      fMStream:TMemoryStream;
      Begin       
      FDQuery := TFDQuery.Create(nil);
         try
            FDQuery.Connection := FDConnection1;
            FDQuery.SQL.Text := query;
            FDQuery.Active := True;
            //fdMemTable1.Data:=fdQuery.Data; {note *2}
            fdMemTable1.CloneCursor(FdQuery,true,true);{note *3}
            fMStream:=TMemoryStream.Create;
            FdMemTable1.SaveToStream(fMStream,sfJson);
         finally
             FDQuery.Free;
             FdMemTable.Close;
         end;
      
    2. 现在您可以阅读JSON内容了 例如,在回答Converting TMemoryStream to 'String' in Delphi 2009

      之后
      function MemoryStreamToString(M: TMemoryStream): string;
      begin
        SetString(Result, PChar(M.Memory), M.Size div SizeOf(Char));
      end;
      

      你有json as String

      1. @VictoriaMarotoSilva建议的BatchMove
      2. 您可以使用BatchMove组件,它提供了在数据集之间移动数据的界面,但是当您想要以驱动器,XML或json格式保存数据时,它更适合备份和导入。我还没有找到例子,使用内存中移动的数据;如果有其他人有例子,请发表评论。

        备注

        1. 使用FdMemTable,不要忘记拖动数据模块的TFDStanStorageJSONLink组件
        2. 方法.Data仅适用于FiredacDatasets(前缀为FD的数据集)。 要在旧数据集中为memTable分配数据,请使用方法.Copydata。
        3. 很抱歉,我将.Data更改为.CloneCursor,与两个数据集共享相同的内存空间。

答案 2 :(得分:0)

考虑使用TFDBatchMove组件。它可以在两个数据库之间直接传输数据,并提供额外的映射支持。因为源和目标可以是任何FireDAC支持的数据库引擎的文本,数据集或SQL查询。

答案 3 :(得分:0)

Delphi MVC Framework包含一个强大的映射器,用于将json映射到对象,将数据集映射到对象。 Mapper是一个子项目。它是独立的代码,也可以用于其他类型的项目。它是开源的!

优点是布尔值例如转换为TJSONBool类型而不是字符串。我建议看看样品。

https://github.com/danieleteti/delphimvcframework/tree/master/samples/objectsmapperssamples

答案 4 :(得分:0)

可能不是最好的解决方案,您可以将其修改为您希望格式化JSON的方式......这是一个快速的示例解决方案:

function GetDataSetAsJSON(DataSet: TDataSet): TJSONObject;
var
  f: TField;
  o: TJSOnObject;
  a: TJSONArray;
begin
  a := TJSONArray.Create;
  DataSet.Active := True;
  DataSet.First;
  while not DataSet.EOF do begin
    o := TJSOnObject.Create;
    for f in DataSet.Fields do
      o.AddPair(f.FieldName, VarToStr(f.Value));
    a.AddElement(o);
    DataSet.Next;
  end;
  DataSet.Active := False;
  Result := TJSONObject.Create;
  Result.AddPair(DataSet.Name, a);
end;