How to serialize & deserialize classes to/from JSON in WEB Core?

SOLUTION: ask ChatGPT!

QUESTION:
Please use the TPerson example to show only the class methods needed to serialize and deserialize using JSON using TMS WEB Core

REPLY:

Sure, here's an example of how to serialize and deserialize a TPerson object using JSON, using only the relevant methods in the class:

unit Unit1;

interface

uses
  System.JSON;

type
  TPerson = class
  private
    FFirstName: string;
    FLastName: string;
    FAge: Integer;
  public
    property FirstName: string read FFirstName write FFirstName;
    property LastName: string read FLastName write FLastName;
    property Age: Integer read FAge write FAge;
    function ToJSON: TJSONObject;
    class function FromJSON(json: TJSONObject): TPerson;
  end;

implementation

{ TPerson }

function TPerson.ToJSON: TJSONObject;
begin
  Result := TJSONObject.Create;
  Result.AddPair('FirstName', FFirstName);
  Result.AddPair('LastName', FLastName);
  Result.AddPair('Age', TJSONNumber.Create(FAge));
end;

class function TPerson.FromJSON(json: TJSONObject): TPerson;
var
  person: TPerson;
begin
  person := TPerson.Create;
  try
    person.FirstName := json.GetValue('FirstName').Value;
    person.LastName := json.GetValue('LastName').Value;
    person.Age := StrToInt(json.GetValue('Age').Value);
  except
    FreeAndNil(person);
    raise;
  end;
  Result := person;
end;

end.

To serialize an instance of TPerson to JSON, you can call its ToJSON method, which returns a TJSONObject instance representing the object's data in JSON format.

To deserialize a TPerson instance from JSON, you can call the FromJSON class method, passing in a TJSONObjectinstance representing the object's data in JSON format. This method returns a new instance of TPerson populated with the data from the JSON object.

Here's an example of how you could use these methods to serialize and deserialize a TPerson instance:

var
  person: TPerson;
  json: TJSONObject;
  jsonString: string;
begin
  // Create a new person object and set its properties
  person := TPerson.Create;
  person.FirstName := 'John';
  person.LastName := 'Doe';
  person.Age := 30;

  // Serialize the person object to JSON
  json := person.ToJSON;
  try
    // Convert the JSON object to a string
    jsonString := json.ToString;
    // Do something with the JSON string
    ShowMessage(jsonString);
  finally
    FreeAndNil(json);
  end;

  // Deserialize the person object from JSON
  json := TJSONObject.ParseJSONValue(jsonString) as TJSONObject;
  try
    person := TPerson.FromJSON(json);
    // Do something with the deserialized person object
    ShowMessage(person.FirstName + ' ' + person.LastName + ', ' + IntToStr(person.Age));
  finally
    FreeAndNil(json);
  end;
end;

=======================================

Instead of the TPerson class, you can give it your own class and it will generate the to/fromJSON methods for you. :slight_smile:

Actually ... maybe not. Is System.JSON available in WEB Core?

Is there ANY JSON parser that works in both VCL and WEB Core?

They all seem to depend on string handling routines in low-level libs that are not compatible in both environments.

what is the conditional compile flag I need to use to have code for both WEB Core and VCL in the same unit?

The conditional compile flag you can use to have code for both WEB Core and VCL in the same unit is {$IFDEF WEBLIB}. This flag can be used to specify code that is only compiled for TMS WEB Core. The corresponding flag for VCL is {$IFNDEF WEBLIB}.

Here is an example of how you can use the conditional compile flag:

unit MyUnit;

interface

uses
{$IFDEF WEBLIB}
  WebLib.JSON;
{$ELSE}
  System.JSON;
{$ENDIF}

type
  TMyClass = class
  public
    {$IFDEF WEBLIB}
    function ToJSON: TJSObject;
    procedure FromJSON(json: TJSObject);
    {$ELSE}
    function ToJSON: TJSONObject;
    procedure FromJSON(json: TJSONObject);
    {$ENDIF}
  end;

implementation

{$IFDEF WEBLIB}
function TMyClass.ToJSON: TJSObject;
begin
  // Code for TMS WEB Core
end;

procedure TMyClass.FromJSON(json: TJSObject);
begin
  // Code for TMS WEB Core
end;
{$ELSE}
function TMyClass.ToJSON: TJSONObject;
begin
  // Code for VCL
end;

procedure TMyClass.FromJSON(json: TJSONObject);
begin
  // Code for VCL
end;
{$ENDIF}

end.

In this example, WebLib.JSON is used if the WEBLIB flag is defined, otherwise System.JSON is used. The ToJSON and FromJSON methods are defined using the appropriate JSON library for the current environment.

Use {$IFDEF PAS2JS}.

hehe ... I was wondering what that symbol might be and ChatGPT just used WEBLIB. I couldn't find it anywhere, so I guessed that was correct. But PAS2JS makes sense as well. I wonder why it chose WEBLIB?

ChatGPT kept spitting out code that I could tell would not work, and wasn't very good at taking my feedback.

I wish there was one common JSON interface that everything could use so this sort of thing wasn't necessary. (I think it should be defined as part of TObject to avoid so many slightly different implementations.)

unit MyUnit;

interface

uses
{$IFDEF PAS2JS}
  WebLib.JSON;
{$ELSE}
  System.JSON;
{$ENDIF}

type
  TMyClass = class
  public
    {$IFDEF PAS2JS}
    function ToJSON: TJSObject;
    procedure FromJSON(json: TJSObject);
    {$ELSE}
    function ToJSON: TJSONObject;
    procedure FromJSON(json: TJSONObject);
    {$ENDIF}
  end;

implementation

{$IFDEF PAS2JS}
function TMyClass.ToJSON: TJSObject;
begin
  // Code for TMS WEB Core
end;

procedure TMyClass.FromJSON(json: TJSObject);
begin
  // Code for TMS WEB Core
end;
{$ELSE}
function TMyClass.ToJSON: TJSONObject;
begin
  // Code for VCL
end;

procedure TMyClass.FromJSON(json: TJSONObject);
begin
  // Code for VCL
end;
{$ENDIF}

end.

Maybe you can ask ChatGPT about it? :slight_smile:

Unit Json and classes like TJSONObject are available in Web Core, but I believe a full object serialization is not implemented with the same interface as Delphi. For object to/from JSON, you should use the regular TJSJson.stringify and TJSJson.parse methods.