From 70265984bb7e322ffd1779d14def249f47496204 Mon Sep 17 00:00:00 2001 From: Daniele Teti Date: Tue, 5 Nov 2024 12:29:44 +0100 Subject: [PATCH] Improved support for Nullable types in URLEncoded serializer (very useful in case of SSV and HTMX) --- .../MVCFramework.Serializer.URLEncoded.pas | 93 ++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/sources/MVCFramework.Serializer.URLEncoded.pas b/sources/MVCFramework.Serializer.URLEncoded.pas index 45a0be3a..fb720459 100644 --- a/sources/MVCFramework.Serializer.URLEncoded.pas +++ b/sources/MVCFramework.Serializer.URLEncoded.pas @@ -119,7 +119,7 @@ type implementation uses - System.NetEncoding, System.Math, JsonDataObjects; + System.NetEncoding, System.Math, JsonDataObjects, MVCFramework.Nullables; { TMVCURLEncodedSerializer } @@ -422,6 +422,14 @@ procedure TMVCURLEncodedSerializer.DataValueToAttribute(const AObject: TObject; const AIgnored: TMVCIgnoredList; const ACustomAttributes: TArray); var RttiType: TRttiType; + lValueTypeInfo: PTypeInfo; + lOutInteger: Integer; + lOutInteger64: Int64; + lOutUInteger64: UInt64; + lOutSingle: Double; + lOutDouble: Double; + lOutExtended: Extended; + lOutUInteger: Cardinal; begin RttiType := nil; AValue.Empty; @@ -432,6 +440,7 @@ begin RttiType := TRttiField(ARttiMember).FieldType; end; + case RttiType.TypeKind of tkString, tkWideString, tkAnsiString, tkUString: AValue := TNetEncoding.URL.Decode(RawData); @@ -446,6 +455,88 @@ begin if SameText(RttiType.ToString, 'boolean') then AValue := RawData.ToBoolean; end; + tkRecord: + begin + if String(RttiType.Handle^.Name).StartsWith('Nullable', True) then + begin + lValueTypeInfo := AValue.TypeInfo; + if lValueTypeInfo = TypeInfo(NullableString) then + begin + AValue := TValue.From(RawData); + end + else if lValueTypeInfo = TypeInfo(NullableInt32) then + begin + if TryStrToInt(RawData, lOutInteger) then + AValue := TValue.From(lOutInteger) + else + AValue := TValue.Empty; + end + else if lValueTypeInfo = TypeInfo(NullableUInt32) then + begin + if TryStrToUInt(RawData, lOutUInteger) then + AValue := TValue.From(lOutUInteger) + else + AValue := TValue.Empty; + end + else if lValueTypeInfo = TypeInfo(NullableInt16) then + begin + if TryStrToInt(RawData, lOutInteger) then + AValue := TValue.From(lOutInteger) + else + AValue := TValue.Empty; + end + else if lValueTypeInfo = TypeInfo(NullableUInt16) then + begin + if TryStrToUInt(RawData, lOutUInteger) then + AValue := TValue.From(lOutUInteger) + else + AValue := TValue.Empty; + end + else if lValueTypeInfo = TypeInfo(NullableInt64) then + begin + if TryStrToInt64(RawData, lOutInteger64) then + AValue := TValue.From(lOutInteger64) + else + AValue := TValue.Empty; + end + else if lValueTypeInfo = TypeInfo(NullableUInt64) then + begin + if TryStrToUInt64(RawData, lOutUInteger64) then + AValue := TValue.From(lOutUInteger64) + else + AValue := TValue.Empty; + end + else if (lValueTypeInfo = TypeInfo(NullableSingle)) then + begin + if TryStrToFloat(RawData, lOutSingle) then + AValue := TValue.From(lOutSingle) + else + AValue := TValue.Empty; + end + else if (lValueTypeInfo = TypeInfo(NullableDouble)) then + begin + if TryStrToFloat(RawData, lOutDouble) then + AValue := lOutDouble + else + AValue := TValue.Empty; + end + else if (lValueTypeInfo = TypeInfo(NullableExtended)) then + begin + if TryStrToFloat(RawData, lOutExtended) then + AValue := lOutExtended + else + AValue := TValue.Empty; + end + else + begin + raise EMVCDeserializationException.Create('(DataValueToAttribute) Cannot deserialize Nullable type ' + String(RttiType.Handle^.Name)); + end; + end + else + begin + raise EMVCDeserializationException.Create('(DataValueToAttribute) Invalid Record Type ' + String(RttiType.Handle^.Name)); + end; + end else raise EMVCDeserializationException.Create('(DataValueToAttribute) Invalid TypeKind: ' + GetEnumName(TypeInfo(TTypeKind), Ord(RttiType.TypeKind))); end;