delphimvcframework icon indicating copy to clipboard operation
delphimvcframework copied to clipboard

Feature request: Аdd the processing properties of type tkDynArray

Open lgadina opened this issue 7 years ago • 2 comments

add the processing properties of type tkDynArray. It is necessary for serialization/deserialization of objects created WSDLImporter.

For example:

class procedure Mapper.ConvertNativeArray(Info: PTypeInfo; P: Pointer;
  AArr: TJSONArray);
var
  ElemInfo: PTypeInfo;
  Dims: Integer;
  Size, I: Integer;
  ObjectInstance: TObject;
  JSObj: TJSONPair;
begin
  GetDynArrayElTypeInfo(Info, ElemInfo, Dims);
  Size := GetDynArrayLength(P);
  for I := 0 to Size - 1 do
    begin
     if ElemInfo.Kind = tkClass then
     begin
      ObjectInstance := TObject(P^);
      AArr.AddElement(ObjectToJSONObject(ObjectInstance));
     end
     else
      case ElemInfo.Kind of
        tkInteger:
        case GetTypeData(ElemInfo).OrdType of
          otSByte,
          otUByte: AArr.AddElement(TJSONNumber.Create(Byte(p^)));
          otSWord,
          otUWord: AArr.AddElement(TJSONNumber.Create(SmallInt(p^)));
          otSLong,
          otULong: AArr.AddElement(TJSONNumber.Create(Integer(p^)));
        end;
        tkFloat:
        case GetTypeData(ElemInfo).FloatType of
          ftSingle: AArr.AddElement(TJSONNumber.Create(Single(p^)));
          ftDouble: if Info = TypeInfo(TDateTime) then
                       AArr.AddElement(TJSONString.Create(ISODateTimeToString(TDateTime(P^))))
                    else
                      AArr.AddElement(TJSONNumber.Create(Double(P^)));
          ftComp: AArr.AddElement(TJSONNumber.Create(Comp(P^)));
          ftCurr: AArr.AddElement(TJSONNumber.Create(Currency(P^)));
          ftExtended: AArr.AddElement(TJSONNumber.Create(Extended(P^)));
        end;
        tkInt64: AArr.AddElement(TJSONNumber.Create(Int64(P^)));
        tkChar: AArr.AddElement(TJSONString.Create(Char(P^)));
        tkWChar: AArr.AddElement(TJSONString.Create(WideChar(P^)));
        tkWString: AArr.AddElement(TJSONString.Create(PWideString(P)^));
        tkString: AArr.AddElement(TJSONString.Create(PShortString(P)^));
        tkLString: AArr.AddElement(TJSONString.Create(PAnsiString(P)^));
        tkUString: AArr.AddElement(TJSONString.Create(PUnicodeString(P)^));
      end;
      P := Pointer( NativeUInt(P) + GetTypeSize(Info));
    end;
end;

class procedure Mapper.ConvertNativeArray(AObject: TObject;
  APropertyName: String; P: Pointer; AArr: TJSONArray);
begin
 ConvertNativeArray(GetPropInfo(AObject, APropertyName)^.PropType^, P, AArr);
end;

class procedure Mapper.ConvertNativeArray(AObject: TObject;
  APropertyName: String; AArr: TJSONArray);
var P: Pointer;
begin
 P := Pointer(GetDynArrayProp(AObject, APropertyName));
 ConvertNativeArray(AObject, APropertyName, P, AArr);
end;
.....
  tkDynArray: ConvertNativeArray(AObject, f, JSONObject);
....

lgadina avatar Aug 04 '17 07:08 lgadina

Nice. Can you propose a PR on the pluggable_mapper branch? (dmvcframework 3.0)

danieleteti avatar Aug 04 '17 08:08 danieleteti

Hmmm... Well, something like this:

procedure TMVCJsonDataObjectsSerializer.SerializeDynamicArray(
  const AValue: TValue;
  const AArray: TJsonArray;
  const AType: TMVCSerializationType;
  const AIgnoredAttributes: TMVCIgnoredList
  );

  function GetTypeSize(Info: PTypeInfo): Cardinal;
  var
    Context: TRttiContext;
    Typ: TRttiType;
  begin
    if Info = TypeInfo(Variant) then
      Exit(SizeOf(TVarData));
    Result := SizeOf(Pointer);
    Typ := Context.GetType(Info);
    if Assigned(Typ) then
      Result := Typ.TypeSize;
  end;

var
  I: Integer;
  Obj: TObject;
  Val: TValue;
  P: Pointer;
begin
  if AValue.GetArrayLength > 0 then
  begin
   P := Pointer(AValue.GetReferenceToRawData^);
   for I := 0 to AValue.GetArrayLength - 1 do
   begin
    Val := AValue.GetArrayElement(i);

     case Val.Kind of
       tkInteger: case GetTypeData(Val.TypeInfo).OrdType of
                    otSByte,
                    otUByte: AArray.Add(Byte(P^));
                    otSWord,
                    otUWord: AArray.Add(SmallInt(P^));
                    otSLong,
                    otULong: AArray.Add(Integer(P^));
                  end;
       tkChar: AArray.Add(Char(P^));
       tkEnumeration: if (Val.TypeInfo = System.TypeInfo(Boolean)) then
                         AArray.Add(Val.AsBoolean)
                      else
                         AArray.Add(GetEnumName(Val.TypeInfo, Val.AsOrdinal));
       tkFloat: case GetTypeData(Val.TypeInfo).FloatType of
                  //System.TypInfo.ftSingle: AArray.Add(Single(p^));
                  System.TypInfo.ftDouble: if Val.TypeInfo = TypeInfo(TDateTime) then
                                              AArray.Add(TDateTime(P^))
                                            else
                                              AArray.Add(Double(P^));
                  System.TypInfo.ftComp: AArray.Add(Comp(P^));
                  System.TypInfo.ftCurr: AArray.Add(Currency(P^));
                  System.TypInfo.ftExtended: AArray.Add(Extended(P^));
                end;
       tkString: AArray.Add(PShortString(P)^);
       tkClass: begin
                  Obj := TObject(P^);
                  ObjectToJsonObject(Obj, AArray.AddObject, GetSerializationType(Obj, AType), AIgnoredAttributes);
                end;
       tkWChar: AArray.Add(WideChar(P^));
       tkLString: AArray.Add(PAnsiString(P)^);
       tkWString: AArray.Add(PWideString(P)^);
       tkArray: SerializeDynamicArray(Val, AArray.AddArray, AType, AIgnoredAttributes);
       tkInt64: AArray.Add(Int64(P^));
       tkDynArray: SerializeDynamicArray(Val, AArray.AddArray, AType, AIgnoredAttributes);
       tkUString: AArray.Add(PUnicodeString(P)^);
       tkRecord: ;
       tkInterface: ;
       tkSet: ;
       tkVariant: ;
     end;
     P := Pointer( NativeUInt(P) + GetTypeSize(Val.TypeInfo));
   end;
  end;
end;

lgadina avatar Aug 04 '17 12:08 lgadina