Jump to content
Sign in to follow this  
DavidRM

Hoping for a Better Way: Delphi Objects to JS Objects

Recommended Posts

I find myself doing this a lot:

type
  TTeamStruct = class (TObject)
    TeamID: integer;
    Name, Desc, Web: string;
    Bonus, Shots, Splats, BonusCurrent, ShotsCurrent, SplatsCurrent: integer;
    procedure FromJSON(json: string);
    function ToJSON: string;
    procedure FromJObject(aObj: Variant);
    function AsJObject: Variant;
  end;

procedure TTeamStruct.FromJSON(json: string);
var
  aObj: Variant;
begin
  asm
    @aObj = JSON.parse(@json);
  end;
  FromJObject(aObj);
end;

function TTeamStruct.ToJSON: string;
var
  aObj: Variant;
begin
  aObj := Self.AsJObject;
  asm
    @Result = JSON.stringify(@aObj);
  end;
end;

procedure TTeamStruct.FromJObject(aObj: Variant);
begin
  TeamID := aObj.teamID;
  Name := aObj.name;
  Desc := aObj.desc;
  Web := aObj.web;
  Bonus := aObj.bonus;
  Shots := aObj.shots;
  Splats := aObj.splats;
  BonusCurrent := aObj.bonusCurrent;
  ShotsCurrent := aObj.shotsCurrent;
  SplatsCurrent := aObj.splatsCurrent;
end;

function TTeamStruct.AsJObject: Variant;
begin
  Result := new JObject;
  Result.teamID :=  TeamID;
  Result.name := Name;
  Result.desc := Desc;
  Result.web := Web;
  Result.bonus := Bonus;
  Result.shots := Shots;
  Result.splats := Splats;
  Result.bonusCurrent := BonusCurrent;
  Result.shotsCurrent := ShotsCurrent;
  Result.splatsCurrent := SplatsCurrent;
end;

I do this to simplify the Json storage, especially for transmitting between client and server.

If I don't do this, I end up with a lot of SMS "artifacts"  in my Json because SMS makes sure all field names are unique (which I totally get).

Is there some trick I can use to *not* have to write this code for pretty much every object flying back and forth?

Thanks!

-David

Share this post


Link to post
Share on other sites

I think you should use the record type to store/retrieve the JSON data.

type
  TFishRecord = record
    Category: String;
    Common_Name: String;
    Length_Cm: String;
    Length_In: String;
    Notes: String;
    Species_Name: String;
    Species_No: String;
  end;

type
  TForm1 = class(TW3Form)
  private
    {$I 'Form1:intf'}
    fishRecord: TFishRecord;
  protected
    procedure InitializeForm; override;
    procedure InitializeObject; override;
    procedure Resize; override;
  end;

implementation

var fishJsonData = #'[
{"Species_No":"90020","Category":"Triggerfishy","Common_Name":"Clown Triggerfish","Species_Name":"Ballistoides conspicillum","Length_Cm":"50","Length_In":"19.6850393700787","Notes":"Also known as the big spotted triggerfish.  Inhabits outer reef areas and feeds upon crustaceans and mollusks by crushing them with powerful teeth.  They are voracious eaters, and divers report seeing the clown triggerfish devour beds of pearl oysters.\r\n\r\nDo not eat this fish.  According to an 1878 account, \"the poisonous flesh acts primarily upon the nervous tissue of the stomach, occasioning violent spasms of that organ, and shortly afterwards all the muscles of the body.  The frame becomes rocked with spasms, the tongue thickened, the eye fixed, the breathing laborious, and the patient expires in a paroxysm of extreme suffering.\"\r\n\r\nNot edible.\r\n\r\nRange is Indo-Pacific and East Africa to Somoa."},
{"Species_No":"90030","Category":"Snapper","Common_Name":"Red Emperor","Species_Name":"Lutjanus sebae","Length_Cm":"60","Length_In":"23.6220472440945","Notes":"Called seaperch in Australia.  Inhabits the areas around lagoon coral reefs and sandy bottoms.\r\n\r\nThe red emperor is a valuable food fish and considered a great sporting fish that fights with fury when hooked.  The flesh of an old fish is just as tender to eat as that of the very young.\r\n\r\nRange is from the Indo-Pacific to East Africa."},
{"Species_No":"90050","Category":"Wrasse","Common_Name":"Giant Maori Wrasse","Species_Name":"Cheilinus undulatus","Length_Cm":"229","Length_In":"90.15748031496059","Notes":"This is the largest of all the wrasse.  It is found in dense reef areas, feeding on a wide variety of mollusks, fishes, sea urchins, crustaceans, and other invertebrates. In spite of its immense size, divers find it a very wary fish.\r\n\r\nEdibility is considered poor.\r\n\r\nRange is the Indo-Pacific and the Red Sea."}
]';

function getList: variant;
begin
  result := JSON.parse(fishJsonData);
end;

function JSON2TFishRecord(const Value: variant): TFishRecord;
begin
  result.Category := Value.Category;
  result.Common_Name := Value.Common_Name;
  result.Length_Cm := Value.Length_Cm;
  result.Length_In := Value.Length_In;
  result.Notes := Value.Notes;
  result.Species_Name := Value.Species_Name;
  result.Species_No := Value.Species_No;
end;

function TFishRecord2JSON(const Value: TFishRecord): variant;
begin
  result := new JObject;
  result.Category := Value.Category;
  result.Common_Name := Value.Common_Name;
  result.Length_Cm := Value.Length_Cm;
  result.Length_In := Value.Length_In;
  result.Notes := Value.Notes;
  result.Species_Name := Value.Species_Name;
  result.Species_No := Value.Species_No;
end;

( TWEdit widget )
categoryEd.Text := fishRecord.Category;

 

Share this post


Link to post
Share on other sites

That can work in simple projects, but as soon as you have to 2 record types with the same field name, the Object Pascal field name no longer matches the JSON field name.

For example, "CategoryID" would be emitted as "CategoryID" (a perfect match) for one record type, but "CategoryID$1" (not so perfect) for another.

-David

Share this post


Link to post
Share on other sites

to match/map the JSON fieldname, you have to declare the record definition is

type
  TFishRecord = record
    Category: String; external 'Category';
    Common_Name: String; external 'Common_Name';
    Length_Cm: String;  external 'Length_Cm';
    Length_In: String; external 'Length_In';
    Notes: String; external 'Notes';
    Species_Name: String; external 'Species_Name';
    Species_No: String; external 'Species_No';
  end;

to emit this JS Object, for instance:

{
    Category : "Snapper",
    Common_Name : "Red Emperor",
    Length_Cm : "60",
    Length_In : "23.6220472440945",
    Notes : "Called seaperch in Australia.",
    Species_Name : "Lutjanus sebae",
    Species_No : "90030"
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×