#1 2023-03-06 16:59:29

chen ken
Member
Registered: 2023-03-06
Posts: 5

How delphi to deserialization json as std::map

when i use mormot/delphi to deserialization a json from c++, there has some string which Serializated from std::map<int,std::string>,such as{"1":"Hello","2":"world"},but i hasn't struct to receive it!

so in delphi i try to serialization a example data,such as: Tarray<Tpair<integer,string>>,but the result is {[{"Key":1,"Value":"Hello"},{"Key":2,"Value":"World"}]}.

how can i deserialization "{"1":"Hello","2":"world"}" and use it in delphi??

thanks!

Offline

#2 2023-03-06 18:28:49

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

Re: How delphi to deserialization json as std::map

I guess that if you use a IKeyValue instance from mormot.core.collections, or just a TSynDictionary from mormot.core.data, the serialization will be as you expect.

Offline

#3 2023-03-06 18:46:03

chen ken
Member
Registered: 2023-03-06
Posts: 5

Re: How delphi to deserialization json as std::map

thank you first! i try it use TIKeyValue<integer, string> or TSynDictionary, but it can not work yet.i view the code, TIKeyValue implemented by two member: "Key" and "Value", it seems no way~

Offline

#4 2023-03-06 19:53:17

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

Re: How delphi to deserialization json as std::map

Just call TSynDictionary.SaveToJson.

You can access the TSynDictionary instance from IKeyValue<integer, string>.Data.
And don't use TIKeyValue<integer, string> but Collections.NewKeyValue<integer, string>.

For some reference about TSynDictionary, see TTestCoreBase._TSynDictionary regression tests.

Offline

#5 2023-03-06 21:15:31

chen ken
Member
Registered: 2023-03-06
Posts: 5

Re: How delphi to deserialization json as std::map

Yes , You are right. I can save and load the TSynDictionary , But I can't use a json string , such as :"{"name":"mark","data":[1,2,3,4,5],"some":{"11.1":"Hello","22.2":",","44.4":"World"}}".

It is so sad~

Maybe I must translater a std::multimap to a std::vector and save it, then I'm able to load and use it in delphi.

Offline

#6 2023-03-06 22:18:18

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

Re: How delphi to deserialization json as std::map

Use a TDocVariant for such content.

Offline

#7 2023-03-06 22:24:55

tbo
Member
Registered: 2015-04-20
Posts: 328

Re: How delphi to deserialization json as std::map

chen ken wrote:

But I can't use a json string , such as :"{"name":"mark","data":[1,2,3,4,5],"some":{"11.1":"Hello","22.2":",","44.4":"World"}}".

const
  _JSON = '{"name":"mark","data":[1,2,3,4,5],"some":{"11.1":"Hello","22.2":",","44.4":"World"}}';
var
  doc: TDocVariantData;
begin
  if doc.InitJson(_JSON) then
  begin
    ShowMessage(doc.S['name']);
    ShowMessage(doc.O['some'].S['11.1']);
    ShowMessage(VarToStr(doc.A['data'].Value[1]));
  end;

With best regards
Thomas

Last edited by tbo (2023-03-06 22:27:26)

Offline

#8 2023-03-07 06:15:09

chen ken
Member
Registered: 2023-03-06
Posts: 5

Re: How delphi to deserialization json as std::map

I can parse any json string , get its key or value. If a json string will be translated to a record, then record must be define , And It's impossible to know the key string and the value in advance,Maybe can RegisterCustomSerializer for it?

Just like:

  TPairString = TPair<double, string>;
  TPairstrings = TArray<TPairString>;
  PPairstrings = ^TPairstrings;

  TDictStringMethod = class
  public
    class procedure CustomReader(var Context: TJsonParserContext; data: pointer);
    class procedure CustomWriter(W: TJsonWriter; data: pointer; Options: TTextWriterWriteObjectOptions);
  end;

initialization
TRttiJson.RegisterCustomSerializer(typeinfo(PPairstrings), TdictStringMethod.CustomReader, TdictStringMethod.CustomWriter);

Can this be work?

Last edited by chen ken (2023-03-07 06:21:32)

Offline

#9 2023-03-07 11:28:39

chen ken
Member
Registered: 2023-03-06
Posts: 5

Re: How delphi to deserialization json as std::map

Thanks very much!now it works, that json string can be translated to TDictionary<double,string> This is my code :

TDstring = TDictionary<double, string>;

class procedure c_method.CustomReadClass(var Context: TJsonParserContext; Instance: TObject);
var
  doc: TDocVariantData;
begin
  if Context.ParseObject then
  begin
    if not assigned(Instance) then
      Instance := TDstring.Create;

    TDstring(Instance).Clear;

    var s : u8string := add_bracket(Context.json); //'{ ' + Context.json + ' }'

    doc.InitJson(s);
    var nameList := doc.Names;

    for var i :integer := 0 to High(nameList) do
    begin
      TDstring(Instance).TryAdd(To_string(nameList[i]).ToDouble, doc.s[nameList[i]]);
    end;

    Context.ParseEndOfObject;
    Context.Valid := true;
  end;

end;

initialization
TRttiJson.RegisterCustomSerializerClass(TDstring, c_method.CustomReadClass, nil);

finalization
TRttiJson.UnRegisterCustomSerializerClass(TDstring);

Thanks again!

Last edited by chen ken (2023-03-07 11:45:15)

Offline

Board footer

Powered by FluxBB