jjw

写给自己的博客。 记录学习的点滴以备查。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

mormot2 笔记(三) 实体转JSON

Posted on 2023-08-25 14:06  jjw  阅读(254)  评论(0编辑  收藏  举报
  TOL = class(TObject)
  public
    procedure W(W: TJsonWriter; Instance: TObject; Options: TTextWriterWriteObjectOptions);
  end;

  TPerson = class
  private
    FName: string;
    FID: integer;
    FSex: Byte;
  published
    property ID: integer read FID write FID;
    property name: string read FName write FName;
    property sex: Byte read FSex write FSex;
  end;

  TTestObject = class
  private
    FL: TObjectList<TPerson>;
  public
    constructor Create;
  published
    property L: TObjectList<TPerson> read FL write FL;
  end;



procedure TForm1.Button3Click(Sender: TObject);
begin
  var OL := TOL.Create;

  var TestObj := TTestObject.Create;
  for var I := 0 to 2 do
  begin
    var p := TPerson.Create;
    p.FName := 'JJW';
    p.FID := 1;
    p.FSex := 1;
    TestObj.L.Add(p);
  end;

  //方法一
  Rtti.RegisterClass(TObjectList<TPerson>).JsonSave := Rtti.RegisterClass(TObjectList).JsonSave;
  Memo1.Text := ObjectToJson(TestObj, [woObjectListWontStoreClassName]);


  //方法二
  var rj := TRttiJson.RegisterCustomSerializerClass(TObjectList<TPerson>, nil, OL.W);
  var jsonStr: RawUtf8;
  SaveJson(TestObj, TypeInfo(TTestObject), [], jsonStr, [woObjectListWontStoreClassName]);
  Memo1.Text := jsonStr;
end;


{ TOL }
procedure TOL.W(W: TJsonWriter; Instance: TObject; Options: TTextWriterWriteObjectOptions);
begin
  W.Add('[');
  var p := TList(Instance);
  for var I := 0 to P.Count-1 do
    W.WriteObject(P[I]);
  w.Add(']');
end;
View Code

针对 每个实体类,必须 TObjectList<TXXXObject> 注册一遍,感觉也挺麻烦的。

补充:

mormot.core.text 单元中 定义了一个全局的类  DefaultJsonWriter: TBaseWriterClass = TTextWriter;

但是mormot框架中,ObjectToJson或SaveJson中有的地方使用了这个全局writer,有些地方直接使用了TJsonWriter.Create.

{ TJsonWriterEx }

procedure TJsonWriterEx.WriteObject(Value: TObject;
  WriteOptions: TTextWriterWriteObjectOptions);
begin
  if Value.ToString.StartsWith('TObjectList<') then
  begin
    Self.Add('[');
    var L := TList(Value);
    for var I := 0 to L.Count-1 do
    begin
      var P := L[I];
      Self.AddString(SaveJson(P, TObject(P).ClassInfo));
    end;
    Self.Add(']');
  end
  else
  begin
    if Self.fInternalJsonWriter<>nil then Form1.Memo1.Lines.Add('????');
//      TTestObject = class
//      private
//        FL: TObjectList<TPerson>;
//      public
//        constructor Create;
//        destructor Destroy; override;
//      published
//        property L: TObjectList<TPerson> read FL write FL;
//      end;
//    Rtti.RegisterClass(Value.ClassType).JsonSave := Rtti.RegisterClass(TObjectList).JsonSave;
    var ri: TRttiCustom := Rtti.RegisterClass(PClass(Value)^);
    var c := ri.Props.Count;
    if c > 0 then
    begin
      for var I := 0 to C-1 do
      begin
        var p := ri.Props.List[I];
        rtti.RegisterType(p.Value.Info);
        p.Value.JsonSave := Rtti.RegisterClass(TObjectList).JsonSave;
      end;
    end;

    inherited;
  end;
View Code

上面的代码并不完善,像TTestObject这样的嵌套类就不行了,需要递归处理,这很不值得,不如直接改写SaveJson或ObjectToJson源代码了。