How to serialize an TList<T> to Json without "garbage"
Asked Answered
A

0

3

I need to serialize this json sting to an Delphi class.

  {
    "Master":{
      "version":"1.0"
    },
    "Details":[
      {
        "idColisEntreeDetail":0,
        "codeBarre":"123456789"
      },
      {
        "idColisEntreeDetail":0,
        "codeBarre":"234567890"
      }
    ]
  }

Here is my class:

unit unit2;

interface

uses Generics.Collections, Rest.Json;

type

  TDetails = class
  private
    FCodeBarre: String;
    FIdColisEntreeDetail: Extended;
  public
    property codeBarre: String read FCodeBarre write FCodeBarre;
    property idColisEntreeDetail: Extended read FIdColisEntreeDetail
      write FIdColisEntreeDetail;
  end;

  TMaster = class
  private
    FVersion: String;
  public
    property version: String read FVersion write FVersion;
  end;

  TMyClass = class
  private
    FDetails: TList<TDetails>;
    FMaster: TMaster;
  public
    property Details: TList<TDetails> read FDetails write FDetails;
    property Master: TMaster read FMaster write FMaster;
    constructor Create;
    destructor Destroy; override;
  end;

implementation

{ TDetails }


{ TMyClass }

constructor TMyClass.Create;
begin
  inherited;
  FMaster := TMaster.Create();
end;

destructor TMyClass.Destroy;
var
  LDetailsItem: TDetails;
begin

  for LDetailsItem in FDetails do
    LDetailsItem.free;

  FMaster.free;
  inherited;
end;

end.

I'm using TJson.ObjectToJsonString(TMyClass) and TJson.JsonToObject<TMyClass>(AJsonString).

My problem is that a lot of garbage is generated when serializing an TList<TDetails> type. For example

  {
    "details":{
      "items":[
      {
        "idColisEntreeDetail":0,
        "codeBarre":"123456789"
      },
      {
        "idColisEntreeDetail":0,
        "codeBarre":"234567890"
      }
      ],
      "count":2,
      "arrayManager":{
      }
    },
    "master":{
      "version":""
    }
  }

It's fine when using an TArray<TDetails> type instead but I'll loose all TList feature.

How can I still use TList type and get a correct Json output ?

Apothegm answered 26/3, 2015 at 10:35 Comment(19)
I'd serialise this manually.Kinnie
Simple, don't use TJson.ObjectToJsonString and TJson.JsonToObject, they are crap as they just stupidly serialize every field.Humpback
Stefan Glienke, is there any alternative ?Apothegm
@StefanGlienke In general, how can a general purpose function know what needs to be serialized? The author of the class needs to tell the serializer what needs to go, and what doesn't.Kinnie
This has a serializer I think: github.com/ahausladen/JsonDataObjectsAbsinthism
@DavidHeffernan Delphi has published directive for marking properties that have to be serialized. Why that wasn't used as starting point in JSON serialization is beyond me.Thriller
@DalijaPrasnikar Well, what if you want to have a member with less than public visibility, but that needs to be serialized?Kinnie
@DavidHeffernan I have yet to find real world example of such thing. If something is not meant for public then it certainly does not need to be serialized.Thriller
List of bug reports covering JSON serialization in QPThriller
@DalijaPrasnikar I've got plenty of such examples in my code.Kinnie
@DavidHeffernan I don't want to enter into discussion about code. What is clear to me is that in Delphi published is marker for serialization, there are also other means for defining data that has to be serialized (DefineBinaryProperty), that is infrastructure that had to be used as foundation, and not something completely out of the line with the way Delphi does things.Thriller
@DalijaPrasnikar The problem is that published affects more than serialization.Kinnie
@DavidHeffernan I am not sure that I follow... if it is public, then published affects only serialization (unless you have been doing some other weird things), if it is not public, then there are other means of defining data for serialization... dumping everything creates serious problems and is incompatible with millions of Delphi classes out there.Thriller
@DalijaPrasnikar I've made my point. Serialization and visibility should be separated.Kinnie
@DavidHeffernan Maybe they should be separated, but they were never separated in Delphi. Two wrongs does not make it right.Thriller
@Dalija Serialization requires fine grained control. Attributes are the way forward.Kinnie
That's what the TJSONMarshal supports (asked e.g. in this post). Don't know how about TJson, but I would expect a similar approach there.Coalfish
The ObjectsMappers contained into the DelphiMVCFramework can do this kind of things quite simply.Codpiece
@Coalfish Problem with attributes is that you cannot inject attribute into class out of your control, like TList is in this case.Thriller

© 2022 - 2024 — McMap. All rights reserved.