delphimvcframework
delphimvcframework copied to clipboard
add a nested json object to the dataset
I've change some code in TMVCJsonDataObjectsSerializer.JsonObjectToDataSet to have the values of a nested json object into the database. (see https://www.facebook.com/groups/delphimvcframework/permalink/2593069444109512/)
Is it possible to add the code into the repositorie?
procedure TMVCJsonDataObjectsSerializer.JsonObjectToDataSet(const AJsonObject: TJDOJsonObject; const ADataSet: TDataSet;
const AIgnoredFields: TMVCIgnoredList; const ANameCase: TMVCNameCase);
var
Field: TField;
sFieldName: string;
sSubName: string;
Name: string;
SS: TStringStream;
SM: TMemoryStream;
NestedDataSet: TDataSet;
procedure ParseFieldName(const aFieldName: string; out aTableName: String; out aColumnName: string);
var
i: Integer;
begin
i := Pos('.', aFieldName);
if i > 1 then
begin
aTableName := Copy(aFieldName, 1, i - 1);
aColumnName := Copy(aFieldName, i + 1);
end
else
begin
aColumnName := '';
aTableName := aFieldName;
end;
end;
begin
if (ADataSet.State in [dsInsert, dsEdit]) then
begin
for Field in ADataSet.Fields do
begin
name := GetNameAs(ADataSet.Owner, Field.Name, Field.FieldName);
if (IsIgnoredAttribute(AIgnoredFields, name)) or (IsIgnoredComponent(ADataSet.Owner, Field.Name)) then
continue;
case GetNameCase(ADataSet, ANameCase) of
ncLowerCase:
name := LowerCase(Field.FieldName);
ncUpperCase:
name := UpperCase(Field.FieldName);
end;
sFieldName := Name;
ParseFieldName(sFieldName, Name, sSubName);
if not AJsonObject.Contains(name) then
continue;
if (AJsonObject[name].Typ = jdtObject) and (AJsonObject.Values[name].ObjectValue = nil) then
// Nullable Type
begin
Field.Clear;
continue;
end;
case Field.DataType of
TFieldType.ftBoolean:
Field.AsBoolean := AJsonObject.B[name];
TFieldType.ftInteger, TFieldType.ftSmallint, TFieldType.ftShortint, TFieldType.ftByte, TFieldType.ftLongWord, TFieldType.ftWord, TFieldType.ftAutoInc:
Field.AsInteger := AJsonObject.I[name];
TFieldType.ftLargeint:
Field.AsLargeInt := AJsonObject.L[name];
TFieldType.ftCurrency:
Field.AsCurrency := AJsonObject.F[name];
TFieldType.ftSingle:
Field.AsSingle := AJsonObject.F[name];
TFieldType.ftFloat, TFieldType.ftFMTBcd, TFieldType.ftBCD:
Field.AsFloat := AJsonObject.F[name];
ftString, ftWideString, ftMemo, ftWideMemo:
begin
if (AJsonObject[name].Typ = jdtObject) then
begin
if sSubName.IsEmpty then
begin
Field.AsWideString := AJsonObject.O[name].ToJSON;
end
else
begin
begin
Field.AsWideString := AJsonObject.O[name].S[sSubName];
end;
end;
end
else
begin
Field.AsWideString := AJsonObject.S[name];
end;
end;
TFieldType.ftDate:
Field.AsDateTime := ISODateToDate(AJsonObject.S[name]);
TFieldType.ftDateTime:
Field.AsDateTime := ISOTimeStampToDateTime(AJsonObject.S[name]);
TFieldType.ftTimeStamp, TFieldType.ftTime:
Field.AsDateTime := ISOTimeToTime(AJsonObject.S[name]);
{$IFDEF TOKYOORBETTER}
TFieldType.ftGuid:
Field.AsGuid := StringToGUID(AJsonObject.S[name]);
{$ENDIF}
TFieldType.ftGraphic, TFieldType.ftBlob, TFieldType.ftStream:
begin
SS := TStringStream.Create(AJsonObject.S[name]);
try
SS.Position := 0;
SM := TMemoryStream.Create;
try
TMVCSerializerHelper.DecodeStream(SS, SM);
TBlobField(Field).LoadFromStream(SM);
finally
SM.Free;
end;
finally
SS.Free;
end;
end;
TFieldType.ftDataSet:
begin
NestedDataSet := TDataSetField(Field).NestedDataSet;
NestedDataSet.First;
while not NestedDataSet.Eof do
NestedDataSet.Delete;
case GetDataType(ADataSet.Owner, Field.Name, dtArray) of
dtArray:
begin
JsonArrayToDataSet(AJsonObject.A[name], NestedDataSet, AIgnoredFields, ANameCase);
end;
dtObject:
begin
NestedDataSet.Edit;
JsonObjectToDataSet(AJsonObject.O[name], NestedDataSet, AIgnoredFields, ANameCase);
NestedDataSet.Post;
end;
end;
end;
else
raise EMVCDeserializationException.CreateFmt('Cannot find type for field "%s"', [Field.FieldName]);
end;
end;
end;
end;
Thanks for your contribute. However, we can merge this code only if the behaviour is simmetric with the serialization side. Can you provide an updated test project to show the serialization and the deserialization process?
Hi, see more in https://github.com/viniciussanchez/dataset-serialize It's perfect
@viniciussanchez the project uses system.json which is quite slow compared to jsondataobjects (used by dmvcframework). Having a subproject for dataset serialization is ok (if adds something to the current implementation), but it should be simple to integrate and must use jsondataobjects. Thank you for suggesting