#1 2014-04-27 05:02:32

avista
Member
Registered: 2014-01-06
Posts: 63

Text Based Record Serialization of Custom Types

The text based definition for record serialization is a very powerful and cool feature, however most of my DTOs use enumerated types. 

When I tried to define a record with an enumerated type, I got a failure when trying to register it:

ESynException with message TJSONCustomParserCustom.Create(unknown "TCONTACTTYPE" type)

type
  TContactType = (ctIndividual, ctCompany);
  TContactData = array of Integer;

  TContact = packed record
    Name: string;
    Address: string;
    ContactType: TContactType;
    Data: TContactData;
  end;
const
  __TContact = 'Name: string; Address: string; ContactType: TContactType; Data: TContactData;';

procedure RegisterContact;
begin
  TTextWriter.RegisterCustomJSONSerializerFromText(TypeInfo(TContact), __TContact);
end;

I also noticed that 'TContactData' won't work either, because it's an unknown type to the parser (even though it's just a redefined type of a dynamic integer array).

Is there a way to define custom types for a text based record definition without having to resort to manually creating a custom serializer via TTextWriter.RegisterCustomJSONSerializer for the entire record?

IMHO, it would be very useful to be able to do this to avoid having to convert enums to/from integers and to define dynamic arrays with meaningful names. 

For example, maybe something like:

TTextWriter.RegisterCustomJSONSerializerType(TypeInfo(TContactType), 'TContactType');
TTextWriter.RegisterCustomJSONSerializerType(TypeInfo(TContactData), 'TContactData');

This would prevent having to write a custom reader/writer for every record that uses these types, so they could be reused in other record definitions.

Maybe I could modify the code to implement something like this with some guidance?

Thanks

Offline

#2 2014-04-27 07:14:47

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,662
Website

Re: Text Based Record Serialization of Custom Types

About the first point, see what the documentation states:

SAD 1.18 pdf page 227 wrote:

For other types (like enumerations or sets), you can simply use the unsigned integer types corresponding to the binary value, e.g. byte word cardinal Int64 (depending on the sizeof() of the initial value).

Note that any previously registered complex type will work.

For simple types, like dynamic arrays, you can just add them.

So you can define your record type as such:

const
  __TContact = 'Name: string; Address: string; ContactType: byte; Data: array of integer;';

Or with the even shorter syntax:

const
  __TContact = 'Name,Address string ContactType byte Data array of integer;';

Your idea to find "a way to define custom types for a text based record definition without having to resort to manually creating a custom serializer via TTextWriter.RegisterCustomJSONSerializer for the entire record" does make sense, of course!
The problem with your proposal is that it won't work with versions of Delphi < 2010, since there is not enough information to find out the exact record layout. Even TContactData = array of Integer do not let TypeInfo(TContactData) have enough information (it states "a dynamic array of 4 bytes of data which does not have any complex type" - but it may be a cardinal, a pointer, a TObject, or four bytes, or one byte, one word, and one byte....).

I've added the corresponding feature request.
See http://synopse.info/fossil/info/954d9f0fd9
We may discuss details in this forum thread.

Offline

#3 2014-04-27 16:42:31

avista
Member
Registered: 2014-01-06
Posts: 63

Re: Text Based Record Serialization of Custom Types

Right now, the text based record serialization is almost perfect for my needs except for these cases.  I really don't want to release my web service API with integers instead of named enumerations, as changing it later will cause customer confusion/problems (and it's not very readable).  I could revert back to using classes with the interface based services, but using records for DTO operations (as you suggested in another response) is certainly preferable.  Now that I have seen the record based functionality, I don't want to go back to using classes for my interface based services. wink

While Mormot is extremely powerful, fast, and obviously well thought out, IMHO it could benefit even more by introducing support for the newer RTTI features.  This would probably open doors for some easier coding styles in Mormot (e.g., generics, property and method attributes, etc.) and would probably increase the options for JSON serialization with classes too.  For those who have existing projects in versions < Delphi 2010, I can certainly understand that existing code should remain stable, however for new features I think it makes sense to consider support for newer language features.

Perhaps to make code maintenance easier, new units could be created that will encapsulate the new features without disrupting the existing code base and without littering the code with $IFDEFS, but I'm sure you have ideas on how to best address that.

In any case, taking one step at a time,  I would really like to see support for newer RTTI starting with text based record serialization.  How can I help to move this forward?

Thanks!

Last edited by avista (2014-04-27 16:46:26)

Offline

Board footer

Powered by FluxBB