2

这是我的第一个问题。对不起我的英语。

我有这样的课程:

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 并为我的 datasnap 应用程序恢复为对象。我对我的数据类型(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 转换为 Object。

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

4

0 回答 0