Search code examples
jsondelphidatasnapdelphi-10-seattle

Rotate a Dataset JSON Result in Datasnap (Delphi 10)


I'm trying to rotate the result of the Datasets returned with Datasnap.

Sample: This is what I get

{"result":[{"table":[["REG_KEY",1,0,0,2,3,0,0,false,false,0,false,false],["REG_NAME",1,1,0,128,129,0,0,false,false,0,false,false]],"REG_KEY":["01","02"],"REG_NAME":["BALEARES","CANARIAS"]}]}

And I want to transform it to just :

[{"REG_KEY":"01","REG_NAME":"BALEARES"},{"REG_KEY":"02","REG_NAME":"CANARIAS"}]

I intend to transform it within the DSHTTPWebDispatcher.FormatResult, but is my first time with DataSnap/REST/JSON and I have problems understanding the classes to manage JSON Values.

It should be something like this:

procedure TWebModule1.DSHTTPWebDispatcher1FormatResult(Sender: TObject; var ResultVal: TJSONValue; const Command: TDBXCommand; var Handled: Boolean);
var
    Aux: TJSONObject;
    NewResult: TJSONObject;
    Row: TJSONObject;
    NumField, NumRow, MaxFields, MaxRows: integer;
begin
    Handled := True;
    NewResult := TJSONArray.Create;
    Aux := TJSONArray(ResultVal).Get(0);  // I get the result as an Object instead of an Array
    MaxFields := Aux.Pairs.Count - 1; // I ignore the Pair 0 because it only contains the Dataset structure
    MaxRows := TJSONArray(1).Count;
    for NumRow := 0 to MaxRows - 1 do begin
        Row := TJSONObject.Create;
        for NumField := 1 to MaxFields do begin
            Row.AddPair(Aux.Pairs[NumField].JsonString, 
                        TJSONArray(Aux.Pairs[NumField].JsonValue).Get(NumRow));
        end;
        Aux.Add(Row);
    end;
    Aux.Free;
    ResultVal.Free;
    ResultVal := NewResult;
end;

But the TJSONObject doesn't have a Pairs.Count method to know how many pairs contains, and the TJSONArray doesn't have and Add method to directly add a new object. I'm quite sure that this code has many other errors.

Can someone direct me how to fix it?


Solution

  • I got it :-)

    This code does the transformation I looked for (it does a double loop iterating through rows and columns, and it rotates the result in a new JSON) :

    procedure TWebModule1.DSHTTPWebDispatcher1FormatResult(Sender: TObject; var ResultVal: TJSONValue; const Command: TDBXCommand; var Handled: Boolean);
    var Aux: TJSONObject;
        NewResult: TJSONValue;
        Row: TJSONObject;
        NumField, NumRow, MaxFields, MaxRows: integer;
    begin  
      Handled := True;
    
      if ResultVal.ToJSON = '[{"table":[]}]' then begin
        TJSONArray(ResultVal).Remove(0);
      end
      else if (LowerCase(Copy(ResultVal.ToJSON, 1, 10)) = '[{"table":') then begin // For Datasets I rotate its content so it comes as rows and not as columns
        NewResult := TJSONArray.Create;
        Aux := TJSONObject(TJSONArray(ResultVal).Get(0));
    
        MaxFields := Aux.Count - 1;  // I ignore the Pair 0 because it only contains the Dataset structure
        MaxRows := TJSONArray(TJSONPair(Aux.Get(1)).JSONValue).Count;
    
        for NumRows := 0 to MaxRows - 1 do begin
          Row := TJSONObject.Create;
          for NumFields := 1 to MaxFields do begin
            Row.AddPair(Aux.Pairs[NumField].JsonString.Value,
                         TJSONArray(Aux.Pairs[NumField].JsonValue).Get(NumRow).Clone as TJSONValue);
          end;
          TJSONArray(NewResult).AddElement(Row);
        end;
    
        ResultVal.Free;              // I free the old Result because a new one is returned (Aux is already supposed to be freed when freeing ResultVal)
        ResultVal := NewResult;       
      end;
    end;