Автоматическая сериализация TObject в JSON с помощью mormot

Я пытаюсь сериализовать объект TO в JSON с помощью фреймворка mORMot. К сожалению, результат всегда нулевой.

Класс, который я пытаюсь сериализовать:

type ApmTime = class(TObject)
private
  function currentTime() : String;
published
  property Current_time: String read currentTime;
public
  constructor Create;
end;

constructor ApmTime.Create;
begin
  inherited;
end;

function ApmTime.currentTime() : String;
begin
  result :=  TimeToStr(Now);
end;

И соответствующий метод mORMot определен в SynCommons:

currentTime := ApmTime.Create;
Write(ObjectToJSON(currentTime, [woFullExpand]));

Это всегда возвращает ноль. После одного шага в TTextWriter.WriteObject (находится в блоке SynCommons), следующий фрагмент кода, кажется, где результирующий json установлен в нуль:

if not(woFullExpand in Options) or
       not(Value.InheritsFrom(TList)
       {$ifndef LVCL} or Value.InheritsFrom(TCollection){$endif}) then
      Value := nil;
  if Value=nil then begin
    AddShort('null');
    exit;

Я ожидаю что-то по линии:

{
  "Current_time" : "15:04"
}

1 ответ

Вчера заглянул в это и выяснил, что происходит, поэтому для будущих людей, наткнувшихся на эту проблему, также:

Если вы добавляете только SynCommons.pas в свое предложение using, тогда DefaultTextWriterJSONClass по умолчанию устанавливается на TTextWriter, который поддерживает только сериализацию определенных типов классов, как вы видели, и не поддерживает произвольные классы / объекты. См. Следующие строки в SynCommons.pas, где установлено это значение по умолчанию:

var
  DefaultTextWriterJSONClass: TTextWriterClass = TTextWriter;

Теперь, чтобы поддерживать сериализацию произвольных объектов в JSON, эту глобальную переменную необходимо изменить с TTextWriter по умолчанию на TJSONSerializer.

Этот класс определен в mORMot.pas, и на самом деле, если вы добавите mORMot.pas в свой раздел uses, его инициализация переопределит указанное выше значение по умолчанию и установит TJSONSerializer в качестве нового значения по умолчанию для вас.

Это поведение фактически задокументировано в SynCommons.pas, если вы читаете достаточно внимательно, например, смотрите комментарии к методу класса "SetDEfaultJSONClass()":

// you can use this method to override the default JSON serialization class
// - if only SynCommons.pas is used, it will be TTextWriter
// - but mORMot.pas initialization will call it to use the TJSONSerializer
// instead, which is able to serialize any class as JSON
class procedure SetDefaultJSONClass(aClass: TTextWriterClass);

Вкратце: чтобы устранить проблему, просто добавьте mORMot.pas в раздел using в дополнение к SynCommons.pas, который у вас уже должен быть.

Попробуйте добавить запись в опубликованную собственность.

property Current_time: String read currentTime write SetCurrentTime. 

Свойство только для чтения не сериализуется. Также ApmTime должен быть основан на TPersistent

type 
  ApmTime = class(TPersistent)
Другие вопросы по тегам