Исчезновение SubDetail TObjectList при JSonToObject

это мой первый вопрос. Извините мой английский.

У меня есть такие классы:

TSFis_S = class(TPersistent)
private
  _SFis_MID  : Integer;
public
  property SFis_MID : Integer read _SFis_MID write _SFis_MID;
end;

TSFis_D = class(TPersistent)
private
  _SFis_MID    : Integer;
  _SFis_S      : TObjectList<TSFis_S>;
public
  property SFis_MID    : Integer read _SFis_MID write _SFis_MID;
  property SFis_S : TObjectList<TSFis_S> read _SFis_S write _SFis_S;
end;

TSFis_M = class(TPersistent)
private
  _SFis_MID : Integer;
  _SFis_D : TObjectList<TSFis_D>;
public
  property SFis_MID    : Integer read _SFis_MID write _SFis_MID;
  property SFis_D      : TObjectList<TSFis_D> read _SFis_D write _SFis_D;
  function ToJSON:TJSONValue;
  destructor Destroy;
end;

Я пытаюсь преобразовать объект TSFis_M в JSon и вернуться к объекту для моего приложения для привязки данных. Я использую конвертеры и ревертеры для своих типов данных (TObjectList и TObjectList)

{ TSFis_M }

function JSonToSFis_M(json: TJSONValue): TSFis_M;
var
  UnMarshaller: TJSONUnMarshal;
begin
  if json is TJSONNull then
    exit(nil);
  UnMarshaller := TJSONUnMarshal.Create;
  try
    UnMarshaller.RegisterReverter(TSFis_M, '_FisTar',
      procedure(Data: TObject; Field: string; Arg: string)
      var
        ctx: TRttiContext;
        datetime :
        TDateTime;
      begin
        datetime := EncodeDateTime(StrToInt(Copy(Arg, 7, 4)), StrToInt(Copy(Arg, 4, 2)), StrToInt(Copy(Arg, 1, 2)), StrToInt
            (Copy(Arg, 12, 2)), StrToInt(Copy(Arg, 15, 2)), StrToInt(Copy(Arg, 18, 2)), 0);
        ctx.GetType(Data.ClassType).GetField(Field).SetValue(Data, datetime);
      end
    );
    UnMarshaller.RegisterReverter(TSFis_D, '_SFis_S',
      procedure(Data: TObject; Field: String; Args: TListOfObjects)
      var
        obj: TObject;
        SFisS: TObjectList<TSFis_S>;
        SFis, SFisNew: TSFis_S;
      begin
        if TSFis_D(Data)._SFis_S=Nil
          then TSFis_D(Data)._SFis_S := TObjectList<TSFis_S>.Create(True);
        SFisS := TSFis_D(Data)._SFis_S;
        SFisS.Clear;
        for obj in Args do
        begin
          SFis := obj as TSFis_S;
          SFisNew := TSFis_S.Create;
          SFisS.Add(SFisNew);
          SFisNew._SFis_MID := SFis._SFis_MID;
        end;
      end
    );
    UnMarshaller.RegisterReverter(TSFis_M, '_SFis_D',
      procedure(Data: TObject; Field: String; Args: TListOfObjects)
      var
        obj: TObject;
        SFisD: TObjectList<TSFis_D>;
        SFis, SFisNew: TSFis_D;
        i: integer;
      begin
        if TSFis_M(Data)._SFis_D=Nil then
          TSFis_M(Data)._SFis_D := TObjectList<TSFis_D>.Create(True);
        SFisD := TSFis_M(Data)._SFis_D;
        SFisD.Clear;
        for obj in Args do
        begin
          SFis := obj as TSFis_D;
          SFisNew := TSFis_D.Create;
          SFisD.Add(SFisNew);
          SFisNew._SFis_MID := SFis._SFis_MID;
        end;
      end
    );
    exit(Unmarshaller.Unmarshal(json) as TSFis_M)
  finally
    UnMarshaller.Free;
  end;
end;

function TSFis_M.ToJSON: TJSONValue;
var
  Marshaller: TJSONMarshal;
begin
  if Assigned(Self) then
  begin
    Marshaller := TJSONMarshal.Create(TJSONConverter.Create);
    try
      Marshaller.RegisterConverter(TSFis_M, '_SFis_D',
                            function(Data: TObject; Field: String): TListOfObjects
                            var
                              FisD: TObjectList<TSFis_D>;
                              i: integer;
                            begin
                              FisD := TSFis_M(Data)._SFis_D;
                              SetLength(Result, FisD.Count);
                              if FisD.Count > 0 then
                                for I := 0 to FisD.Count - 1 do
                                  Result[I] := FisD[i];
                            end);
      Marshaller.RegisterConverter(TSFis_M, '_FisTar',
                            function(Data: TObject; Field: string): string
                            var
                              ctx: TRttiContext; date : TDateTime;
                            begin
                              date := ctx.GetType(Data.ClassType).GetField(Field).GetValue(Data).AsType<TDateTime>;
                              Result := FormatDateTime('dd.mm.yyyy hh:nn:ss', date);
                            end);
      Marshaller.RegisterConverter(TSFis_D, '_SFis_S',
                            function(Data: TObject; Field: String): TListOfObjects
                            var
                              FisD: TObjectList<TSFis_S>;
                              i: integer;
                            begin
                              FisD := TSFis_D(Data)._SFis_S;
                              SetLength(Result, FisD.Count);
                              if FisD.Count > 0 then
                                for I := 0 to FisD.Count - 1 do
                                  Result[I] := FisD[i];
                            end);

      exit(Marshaller.Marshal(Self))
    finally
      Marshaller.Free;
    end;
  end
  else
    exit(TJSONNull.Create);
end;

И, наконец, например, я поместил на форму 1 кнопку и 2 памятки. И я пытаюсь преобразовать созданный мной объект в Json, Json.ToString в Memo1. И преобразуйте этот JSonValue в объект.

procedure TForm1.Button1Click(Sender: TObject);
var
  MainFis : TSFis_M;
  MainFis2 : TSFis_M;
  DFis    : TSFis_D;
  SFis    : TSFis_S;
begin
  MainFis := TSFis_M.Create;
  MainFis.SFis_D := TObjectList<TSFis_D>.Create(True);
  DFis := TSFis_D.Create;
  DFis._SFis_MID := 1;
  MainFis.SFis_D.Add(DFis);
  SFis := TSFis_S.Create;
  SFis._SFis_MID := 1;
  DFis.SFis_S := TObjectList<TSFis_S>.Create(True);
  DFis.SFis_S.Add(SFis);
  Memo1.Text := MainFis.ToJSON.ToString;
  Edit1.Text := IntToStr(MainFis.SFis_D[0].SFis_S.Count);
  MainFis2 := JSonToSFis_M(MainFis.ToJSON);
  Edit2.Text := IntToStr(MainFis2.SFis_D[0].SFis_S.Count); // Access violation. Because MainFis2.SFis_D[0].SFis_S = Nil Now (That's the my problem. Why?)
  Memo2.Text := MainFis2.ToJSon.ToString;
end;

Но когда я делаю это. TSFis_S исчезает. На первом этапе (ObjectToJSon) проблем нет.

{"type":"Unit1.TSFis_M","id":1,"fields": 
    {"_SFis_MID":0,"_SFis_D":
      [ {"type":"Unit1‌​.TSFis_D","id":2,"fields":
            {"_SFis_MID":1,"_SFis_S":
                [ {"type":"Unit1.TSFis_S","id":‌​3,"fields":{"_SFis_MID":1} } ] 
            }
      } ]
    }
}

Но когда я пытаюсь вернуться к объектному ревертеру, все идет не так.

Я не могу найти проблему. В чем моя вина.

Спасибо

PS: Если я не объяснил, пример кода здесь: http://goo.gl/3QnSw


person Ercument Eskar    schedule 17.04.2013    source источник
comment
если вы уверены, что на первом этапе нет проблем с сериализацией, то, возможно, начните с отображения строки JSON и только последовательности десериализации? PS. Также, пожалуйста, добавьте в теги вашу версию Delphi.   -  person Arioch 'The    schedule 18.04.2013
comment
некоторые другие библиотеки также имели специальную настройку для списков объектов, таких как stackoverflow.com/questions/2882894 и stackoverflow.com/questions/7841617 или blog.synopse.info/post/2013/01/18/   -  person Arioch 'The    schedule 18.04.2013
comment
Я использую Delphi XE3. Да, я уверен, что нет проблем с сериализацией. Строка Json после первого шага: {type:Unit1.TSFis_M,id:1,fields:{_SFis_MID:0,_SFis_D:[{type:Unit1.TSFis_D,id:2,fields:{_SFis_MID:1,_SFis_S:[{ тип: Unit1.TSFis_S, идентификатор: 3, поля: {_SFis_MID: 1}}]}}]}}   -  person Ercument Eskar    schedule 18.04.2013
comment
Я только что попробовал в решении stackoverflow.com/questions /2882894/ Не работает.   -  person Ercument Eskar    schedule 18.04.2013
comment
функция TSFis_M.ToJSON: TJSONValue; Маршаллер: = TJSONMarshal.Create(TJSONConverter.Create);   -  person Arioch 'The    schedule 18.04.2013
comment
функция JSonToSFis_M(json: TJSONValue): UnMarshaller := TJSONUnMarshal.Create;   -  person Arioch 'The    schedule 18.04.2013
comment
возможный дубликат Generics и Marshal/UnMarshal. Что я здесь упускаю?   -  person Arioch 'The    schedule 18.04.2013
comment
Я только что попробовал решение stackoverflow.com/questions/2882894/… Не сработало Это решение для другой библиотеки. Многие считают библиотеку Embarcadero JSON хуже (медленной, глючной, только для Delphi) по сравнению с альтернативами (я дал ссылки на пару). Подумайте, стоит ли тратить время на DBX JSON.   -  person Arioch 'The    schedule 18.04.2013
comment
Да, кажется, я должен исследовать другие библиотеки. (Даже я не хочу) Я не буду терять на это время. Спасибо Ариох.   -  person Ercument Eskar    schedule 18.04.2013
comment
помогло ли исправление TJSONMarshal.Create вашей проблеме? действительно ли это был дубликат stackoverflow.com/questions/7528829?   -  person Arioch 'The    schedule 18.04.2013
comment
Нет, не дубликат. Моя проблема не в преобразовании TObjectList > JSon. Моя проблема заключается в возврате JSon к TObjectList TObjeclist. И я уже использую TJSONMarshal.Create(TJSONConverter.Create); и TJSONUnMarshal.Create; как это. Я не вижу никакой разницы между моим кодом и вашим. Что ты имел в виду подправить?   -  person Ercument Eskar    schedule 19.04.2013