Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8251383
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 8, 20262026-06-08T00:13:06+00:00 2026-06-08T00:13:06+00:00

Is there a way to convert this Record TError = record code: Word; message:

  • 0

Is there a way to convert this Record

TError = record
  code: Word;
  message: String;
end;

TState = record
  caption: String;
  address: Cardinal;
  counters: TArray<Word>;
  errors: TArray<TError>;
end;

to serialized Form Data string (Content-Type: application/x-www-form-urlencoded) like

caption=Foo&
address=175896&
counters[]=2&
counters[]=2&
errors[0][code]=52&
errors[0][message]=ERR_NOT_AVAILABLE

for sending via HTTP?

Maybe there is some function similar to JQuery.param()?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-08T00:13:08+00:00Added an answer on June 8, 2026 at 12:13 am

    Ok, here is a boilerplate solution which can be adapted for your specific serialization or other use as well.

    A record, TSerializer, does all the serialization job and the result is stored in a string list.

    To use it, call method Serialize('state', TValue.From(state),sList); from a TSerializer instance.

    You can add most types that fit into a TValue, including records, static arrays, dynamic arrays and simple classes. The unwinding of all elements are made by recursion.
    (Disclaimer, this is tested on XE2, but I think Delphi-2010 supports all enhanced-RTTI calls used here)

    The output from your example looks like this:

    record state:TState
      caption:string=Foo
      address:Cardinal=175896
      dynamic array counters:Word
        counters[0]:Word=2
        counters[1]:Word=2
      end
      dynamic array errors:TError
        record errors[0]:TError
          code:Word=52
          message:string=ERR_NOT_AVAILABLE
        end
      end
    end
    

    Here is the source unit:

    unit SerializerBoilerplate;
    
    interface
    
    uses
      System.SysUtils, Classes, RTTI, TypInfo;
    
    Type
      TSerializer = record
      private
        FSumIndent: string;
        procedure IncIndent;
        procedure DecIndent;
      public
        procedure Serialize(const name: string; thing: TValue;
          sList: TStrings; first: boolean = true);
      end;
    
    implementation
    
    procedure TSerializer.IncIndent;
    begin
      FSumIndent := FSumIndent + '  ';
    end;
    
    procedure TSerializer.DecIndent;
    begin
      SetLength(FSumIndent, Length(FSumIndent) - 2);
    end;
    
    procedure TSerializer.Serialize(const name: string; thing: TValue;
      sList: TStrings; first: boolean);
    type
      PPByte = ^PByte;
    var
      LContext: TRTTIContext;
      LField: TRTTIField;
      LProperty: TRTTIProperty;
      LRecord: TRTTIRecordType;
      LClass: TRTTIInstanceType;
      LStaticArray: TRTTIArrayType;
      LDynArray: TRTTIDynamicArrayType;
      LDimType: TRttiOrdinalType;
      LArrayIx: array of integer;
      LArrayMinIx: array of integer;
      LArrayMaxIx: array of integer;
      LNewValue: TValue;
      i: integer;
      // Generic N-dimensional array indexing
      procedure IncIx(var ArrayIx, ArrayMinIx, ArrayMaxIx: array of integer);
      var
        dimIx: integer;
      begin
        dimIx := Length(ArrayIx) - 1;
        repeat
          if (ArrayIx[dimIx] < ArrayMaxIx[dimIx]) then
          begin
            Inc(ArrayIx[dimIx]);
            break;
          end
          else
          begin
            ArrayIx[dimIx] := ArrayMinIx[dimIx];
            Dec(dimIx);
            if (dimIx < 0) then
              break;
          end;
        until (true = false);
      end;
      // Convert N-dimensional index to a string
      function IxToString(const ArrayIx: array of integer): string;
      var
        i: integer;
      begin
        Result := '';
        for i := 0 to High(ArrayIx) do
          Result := Result + '[' + IntToStr(ArrayIx[i]) + ']';
      end;
      // Get correct reference
      function GetValue(Addr: Pointer; Typ: TRTTIType): TValue;
      begin
        TValue.Make(Addr, Typ.Handle, Result);
      end;
    
    begin
      if first then
        FSumIndent := '';
    
      case thing.Kind of
        { - Number calls }
        tkInteger, // Identifies an ordinal type.
        tkInt64, // Identifies the Int64/UInt64 types.
        tkPointer: // Identifies a pointer type.
          begin
            sList.Add(FSumIndent + name + ':' + thing.TypeInfo.name + '=' +
              thing.ToString);
          end;
        tkEnumeration:
          begin
            if (thing.TypeInfo = TypeInfo(boolean)) then
            begin
              sList.Add(FSumIndent + name + ':' + thing.TypeInfo.name + '=' +
                BoolToStr(thing.AsBoolean));
            end
            else begin
              // ToDO : Implement this
            end;
          end; // Identifies an enumeration type.
        tkSet: // Identifies a set type.
          begin
            // ToDO : Implement this
          end;
        { - Float calls }
        tkFloat: // Identifies a floating-point type. (plus Date,Time,DateTime)
          begin
            if (thing.TypeInfo = TypeInfo(TDate)) then
            begin
              sList.Add(FSumIndent + name + ':' + thing.TypeInfo.name + '=' +
                DateToStr(thing.AsExtended));
            end
            else if (thing.TypeInfo = TypeInfo(TTime)) then
            begin
              sList.Add(FSumIndent + name + ':' + thing.TypeInfo.name + '=' +
                TimeToStr(thing.AsExtended));
            end
            else if (thing.TypeInfo = TypeInfo(TDateTime)) then
            begin
              sList.Add(FSumIndent + name + ':' + thing.TypeInfo.name + '=' +
                DateTimeToStr(thing.AsExtended));
            end
            else
            begin
              sList.Add(FSumIndent + name + ':' + thing.TypeInfo.name + '=' +
                FloatToStr(thing.AsExtended));
            end;
            // ToDO : Handle currency
          end;
    
        { - String,character calls }
        tkChar, // Identifies a single-byte character.
        tkString, // Identifies a short string type.
        tkLString: // Identifies an AnsiString type.
          begin
            sList.Add(FSumIndent + name + ':' + thing.TypeInfo.name + '=' +
              thing.AsString);
          end;
        tkWString: // Identifies a WideString type.
          begin
            sList.Add(FSumIndent + name + ':' + thing.TypeInfo.name + '=' +
              thing.ToString);
          end;
        tkInterface: // Identifies an interface type.
          begin
            // ToDO : Implement this
          end;
        tkWChar, // Identifies a 2-byte (wide) character type.
        tkUString: // Identifies a UnicodeString type.
          begin
            sList.Add(FSumIndent + name + ':' + thing.TypeInfo.name + '=' +
              thing.AsString);
          end;
    
        tkVariant: // Identifies a Variant type.
          begin
            // ToDO : Implement this
          end;
    
        { - Generates recursive calls }
        tkArray: // Identifies a static array type.
          begin
            LStaticArray := LContext.GetType(thing.TypeInfo) as TRTTIArrayType;
            SetLength(LArrayIx, LStaticArray.DimensionCount);
            SetLength(LArrayMinIx, LStaticArray.DimensionCount);
            SetLength(LArrayMaxIx, LStaticArray.DimensionCount);
            sList.Add(FSumIndent + 'static array ' + name + ':' +
              LStaticArray.ElementType.name);
            IncIndent();
            for i := 0 to LStaticArray.DimensionCount - 1 do
            begin
              LDimType := LStaticArray.Dimensions[i] as TRttiOrdinalType;
              LArrayMinIx[i] := LDimType.MinValue;
              LArrayMaxIx[i] := LDimType.MaxValue;
              LArrayIx[i] := LDimType.MinValue;
            end;
            for i := 0 to LStaticArray.TotalElementCount - 1 do
            begin
              Serialize(Name + IxToString(LArrayIx),
                GetValue( PByte(thing.GetReferenceToRawData) +
                  LStaticArray.ElementType.TypeSize * i,
                  LStaticArray.ElementType),
                sList,false);
              IncIx(LArrayIx, LArrayMinIx, LArrayMaxIx);
            end;
            DecIndent();
            sList.Add(FSumIndent + 'end');
          end;
        tkDynArray: // Identifies a dynamic array type.
          begin
            LDynArray := LContext.GetType(thing.TypeInfo) as TRTTIDynamicArrayType;
            sList.Add(FSumIndent + 'dynamic array ' + name + ':' +
              LDynArray.ElementType.name);
            IncIndent();
            for i := 0 to thing.GetArrayLength - 1 do
            begin
              Serialize(Name + '[' + IntToStr(i) + ']',
                GetValue( PPByte(thing.GetReferenceToRawData)^ +
                  LDynArray.ElementType.TypeSize * i,
                  LDynArray.ElementType),
                sList,false);
            end;
            DecIndent();
            sList.Add(FSumIndent + 'end');
          end;
        tkRecord: // Identifies a record type.
          begin
            sList.Add(FSumIndent + 'record ' + name +':' +thing.TypeInfo.name);
            LRecord := LContext.GetType(thing.TypeInfo).AsRecord;
            IncIndent();
            for LField in LRecord.GetFields do
            begin
              Serialize(LField.name, LField.GetValue(thing.GetReferenceToRawData),
                sList, false);
            end;
            DecIndent();
            sList.Add(FSumIndent + 'end');
          end;
        tkClass: // Identifies a class type.
          begin
            sList.Add(FSumIndent + 'object ' + name + ':' + thing.TypeInfo.name);
            IncIndent();
            LClass := LContext.GetType(thing.TypeInfo).AsInstance;
            for LField in LClass.GetFields do
            begin
              Serialize(LField.name,
                // A hack to get a reference to the object
                // See https://stackoverflow.com/questions/2802864/rtti-accessing-fields-and-properties-in-complex-data-structures
                GetValue(PPByte(thing.GetReferenceToRawData)^ + LField.Offset,
                LField.FieldType),
                sList,false);
            end;
            // ToDO : Implement a more complete class serializer
            DecIndent();
            sList.Add(FSumIndent + 'end');
          end;
    
        { - Not implemented }
        tkClassRef: ; // Identifies a metaclass type.
        tkMethod: ; // Identifies a class method type.
        tkProcedure: ; // Identifies a procedural type.
        tkUnknown: ; // Identifies an unknown type that has RTTI.
      end;
    end;
    
    end.
    

    And a test unit:

    program SerializerProj;
    
    {$APPTYPE CONSOLE}
    {$R *.res}
    
    uses
      Classes,
      SysUtils,
      RTTI,
      SerializerBoilerplate;
    
    Type
      TMyObj = Class
      private
        fI: integer;
        fS: string;
      end;
    
      TInnerRec = record
        A, B, C: string;
      end;
    
      TDim1 = 1 .. 3;
      TDim2 = 2 .. 5;
      TMyArr = array [TDim1, TDim2] of integer; // Must be typed dimensions
    
      TTestRec = record
        s: string;
        ws: WideString;
        st: ShortString;
        ansiCh: AnsiChar;
        ansiS: AnsiString;
        wChar: Char;
        B: boolean;
        i: integer;
        t: TTime;
        d: TDate;
        dt: TDateTime;
        fd: Double;
        fS: Single;
        r: TInnerRec;
        arr: TMyArr;
        dArr: array of string;
        o: TMyObj;
      end;
    
      TError = record
        code: Word;
        message: String;
      end;
    
      TState = record
        caption: String;
        address: Cardinal;
        counters: TArray<Word>;
        errors: TArray<TError>;
      end;
    
    var
      tr: TTestRec;
      state: TState;
      sList: TStringList;
      s: string;
      Serializer: TSerializer;
    
    begin
      state.caption := 'Foo';
      state.address := 175896;
      SetLength(state.counters,2);
      state.counters[0] := 2;
      state.counters[1] := 2;
      SetLength(state.errors,1);
      state.errors[0].code := 52;
      state.errors[0].message := 'ERR_NOT_AVAILABLE';
    
      tr := Default (TTestRec);
      sList := TStringList.Create;
      try
        tr.s := 'A';
        tr.ws := 'WS';
        tr.st := '[100]';
        tr.ansiCh := '@';
        tr.ansiS := '@!';
        tr.wChar := 'Ö';
        tr.B := true;
        tr.i := 100;
        tr.t := Now;
        tr.d := Now;
        tr.dt := Now;
        tr.fd := Pi;
        tr.fS := 2 * Pi;
        tr.r.A := 'AA';
        tr.r.B := 'BB';
        tr.r.C := 'CC';
        tr.arr[1, 2] := 12;
        tr.arr[1, 3] := 13;
        tr.arr[1, 4] := 14;
        tr.arr[1, 5] := 15;
        tr.arr[2, 2] := 22;
        tr.arr[2, 3] := 23;
        tr.arr[2, 4] := 24;
        tr.arr[2, 5] := 25;
        tr.arr[3, 2] := 32;
        tr.arr[3, 3] := 33;
        tr.arr[3, 4] := 34;
        tr.arr[3, 5] := 35;
        SetLength(tr.dArr, 3);
        tr.dArr[0] := 'A';
        tr.dArr[1] := 'B';
        tr.dArr[2] := 'C';
        tr.o := TMyObj.Create;
        tr.o.fI := 11;
        tr.o.fS := '22';
    
        Serializer.Serialize('tr', TValue.From(tr), sList);
        for s in sList do
          WriteLn(s);
        sList.Clear;
        Serializer.Serialize('state', TValue.From(state),sList);
        for s in sList do
          WriteLn(s);
    
        ReadLn;
      finally
        sList.Free;
      end;
    
    end.
    

    I had a little help studying Barry Kellys answer to the question Rtti accessing fields and properties in complex data structures.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Is there an easy way to convert date and time like this: Sun, 14
Is there a way to convert an integer to a string in PHP?
Is there a way to convert @my_variable string into a value of @my_variable ?
Is there a way to convert twitter bootstrap's typeahead function into a $(body).on() function?
Is there any way to convert a android.graphics.Bitmap instance into jpeg in android?
Is there a way to convert a Java application into a Mac OS X
Is there a way to convert HTML into XAML? I noticed that you can
Is there any way to convert from DB.Null to decimal in C#? Like Object[]
Is there a way to convert an int to a bitmask? example: int i
Is there a way to convert a vector to a pointer to a pointer

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.