#1 2021-02-01 15:08:11

dc
Member
Registered: 2012-11-16
Posts: 46

migrating from old mORMot version - JSONDecode

Hi,

I'm trying to migrate my projects from a pretty old version of mORMot from year 2018 and encountered a problem with JSONDecode method, which was changed and no longer accepts Values in dynamic form:

  Values: TPUtf8CharDynArray;

While searching forum I've found this post https://synopse.info/forum/viewtopic.ph … 876#p29876 and of course there is also description in documentation (chapter 10.1.6.1. Custom class serialization).

Solution provided there, however, is not satisfying for me, because I don't know in advance how many items I'll need, therefore I can not really use a static array.

I tried to use this:

  Values: TValuePUTF8CharArray;

but it gives me AV, and that made me come up with this ugly workaround:

  Values: array[0..10000] of TValuePUTF8Char;

I'd really like to know what is the proper way of implementing custom reader nowadays?

Thanks in advance.

Offline

#2 2021-02-01 15:46:15

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

Re: migrating from old mORMot version - JSONDecode

Perhaps you are in fact searching for the following function:

function JsonDecode(P: PUtf8Char; out Values: TNameValuePUtf8CharDynArray;
  HandleValuesAsObjectOrArray: boolean = false): PUtf8Char; overload;

But with a custom reader, you should know the field names first, so the TJsonParserContext.ParseObject method with the fixed names parameter is to be used.

Note that the custom read/write functions did change from mORMot 1.18 type, because the JSON serialization process has been rewritten from scratch.
You you need to rewrite the callback functions.

See TCollTstDynArray class in test.core.data.pas as reference for custom reader/writer methods.
A typical reader is the following:

class procedure TCollTstDynArray.FVReader2(var Context: TJsonParserContext;
  Data: pointer);
var
  Values: array[0..5] of TValuePUtf8Char;
begin
  // '{"Major":1,"Minor":2001,"Release":3001,"Build":4001,"Main":"1","Detailed":"1001"},..
  if Context.ParseObject([
     'Major', 'Minor', 'Release', 'Build', 'Main', 'Detailed'], @Values) then
    with PFV(Data)^ do
    begin
      Major := Values[0].ToInteger;
      Minor := Values[1].ToInteger;
      Release := Values[2].ToInteger;
      Build := Values[3].ToInteger;
      Main := Values[4].ToString;
      Detailed := Values[5].ToString;
    end;
end;

I guess the new way is not so difficult to use.

Offline

#3 2021-02-01 23:38:02

dc
Member
Registered: 2012-11-16
Posts: 46

Re: migrating from old mORMot version - JSONDecode

ab wrote:

Perhaps you are in fact searching for the following function:

function JsonDecode(P: PUtf8Char; out Values: TNameValuePUtf8CharDynArray;
  HandleValuesAsObjectOrArray: boolean = false): PUtf8Char; overload;

Yes, it seems that TNameValuePUtf8CharDynArray does the trick, thank you!

ab wrote:

But with a custom reader, you should know the field names first, so the TJsonParserContext.ParseObject method with the fixed names parameter is to be used.

Unfortunately I don't know field names in advance because I use it as a serializer/deserializer for custom models in generic way. That's why I cannot use static arrays.

Will need to do some more advanced tests, but it looks promising for now smile

Thank again for fast response, it's much apprecated.

Offline

Board footer

Powered by FluxBB