Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | {1975} fixed nasty issue with JSON serialization of custom records (e.g. TGUID) |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
e9631f62183c5eba8047bca4608b24be |
User & Date: | ab 2015-10-09 09:29:46 |
2015-10-09
| ||
09:30 | {1976} TGUID will now be accepted as SOA argument in all versions of Delphi check-in: 257cf80432 user: ab tags: trunk | |
09:29 | {1975} fixed nasty issue with JSON serialization of custom records (e.g. TGUID) check-in: e9631f6218 user: ab tags: trunk | |
08:09 | {1974} fixed contract recognition error when ResultAsJSONObjectWithoutResult is set check-in: 890f86545b user: ab tags: trunk | |
Changes to SynCommons.pas.
5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 ..... 30136 30137 30138 30139 30140 30141 30142 30143 30144 30145 30146 30147 30148 30149 30150 ..... 31513 31514 31515 31516 31517 31518 31519 31520 31521 31522 31523 31524 31525 31526 31527 31528 31529 31530 31531 31532 31533 31534 31535 ..... 31540 31541 31542 31543 31544 31545 31546 31547 31548 31549 31550 31551 31552 31553 31554 31555 31556 ..... 31564 31565 31566 31567 31568 31569 31570 31571 31572 31573 31574 31575 31576 31577 31578 ..... 31604 31605 31606 31607 31608 31609 31610 31611 31612 31613 31614 31615 31616 31617 31618 31619 31620 31621 31622 ..... 32283 32284 32285 32286 32287 32288 32289 32290 32291 32292 32293 32294 32295 32296 32297 32298 32299 32300 32301 32302 32303 32304 32305 32306 32307 32308 32309 32310 32311 32312 32313 32314 32315 32316 32317 32318 ..... 32328 32329 32330 32331 32332 32333 32334 32335 32336 32337 32338 32339 32340 32341 |
// - to be called if TypeNameToSimpleRTTIType() did fail, i.e. return ptCustom // - will return ptCustom for any unknown type class function TypeInfoToSimpleRTTIType(Info: pointer; ItemSize: integer): TJSONCustomParserRTTIType; /// unserialize some JSON content into its binary internal representation function ReadOneLevel(var P: PUTF8Char; var Data: PByte; Options: TJSONCustomParserSerializationOptions): boolean; virtual; /// serialize a binary internal representation into JSON content procedure WriteOneLevel(aWriter: TTextWriter; var P: PByte; Options: TJSONCustomParserSerializationOptions); virtual; /// the associated type name, e.g. for a record property CustomTypeName: RawUTF8 read fCustomTypeName; /// the property name // - may be void for the Root element // - e.g. 'SubProp' ................................................................................ asm // faster version by AB (direct call to finalization procedures) { -> EAX pointer to record to be finalized } { EDX pointer to type info } { <- EAX pointer to record to be finalized } movzx ecx,byte ptr [edx].TFieldTable.NameLen push ebx mov ebx,eax push esi push edi mov edi,[edx+ecx].TFieldTable.ManagedCount lea esi,[edx+ecx].TFieldTable.ManagedFields test edi,edi jz @@end @@loop: mov edx,[esi].TFieldInfo.TypeInfo mov eax,[esi].TFieldInfo.&Offset ................................................................................ begin inherited; fNestedArray.Free; end; procedure TJSONCustomParserCustomSimple.CustomWriter( const aWriter: TTextWriter; const aValue); var i,int: integer; V: PByte; begin case fKnownType of ktStaticArray: begin aWriter.Add('['); V := @aValue; for i := 1 to PArrayTypeInfo(fTypeData)^.elCount do fNestedArray.WriteOneLevel(aWriter,V,[]); aWriter.CancelLastComma; aWriter.Add(']'); end; (* max: integer; item: PShortString; ktSet: begin // written as an object with set names as fields = true/false aWriter.Add('{'); item := GetEnumBaseTypeList(fTypeData,max); ................................................................................ inc(PByte(item),ord(item^[0])+1); // next short string end; aWriter.CancelLastComma; aWriter.Add('}'); end; *) ktEnumeration, ktSet: begin int := 0; MoveFast(aValue,int,fDataSize); aWriter.AddU(int); // storing the value as binary/integer is safe and fast //aWriter.AddShort(GetEnumName(fCustomTypeInfo,byte(aValue))^); end; ktDynamicArray: raise ESynException.CreateUTF8('%.CustomWriter("%"): Unsupported', [self,fCustomTypeName]); else begin // encoded as JSON strings aWriter.Add('"'); ................................................................................ end; end; end; function TJSONCustomParserCustomSimple.CustomReader(P: PUTF8Char; var aValue; out EndOfObject: AnsiChar): PUTF8Char; var PropValue: PUTF8Char; V,i: integer; wasString: boolean; Val: PByte; begin result := nil; // indicates error case fKnownType of ktStaticArray: begin if P^<>'[' then ................................................................................ if wasString and (TextToGUID(PropValue,@aValue)<>nil) then result := P; ktSet,ktEnumeration: begin if wasString then if fKnownType=ktSet then raise ESynException.CreateUTF8('%.CustomReader("%") not implemented yet from string', [self,fCustomTypeName]) else V := GetEnumNameValue(fCustomTypeInfo,PropValue,StrLen(PropValue)) else V := GetInteger(PropValue); if V<0 then exit; MoveFast(V,aValue,fDataSize); result := P; end; ktFixedArray: if wasString and (StrLen(PropValue)=fFixedSize*2) and SynCommons.HexToBin(PAnsiChar(PropValue),@aValue,fFixedSize) then result := P; end; ................................................................................ inc(aWriter.fHumanReadableLevel); DynArray := PPointer(Value)^; if DynArray<>nil then for j := 1 to DynArrayLength(DynArray) do begin if soWriteHumanReadable in Options then aWriter.AddCRAndIndent; if Prop.NestedProperty[0].PropertyName='' then // array of simple WriteOneValue(Prop.NestedProperty[0],DynArray) else begin Prop.WriteOneLevel(aWriter,DynArray,Options); // array of record aWriter.Add(','); end; {$ifdef ALIGNCUSTOMREC} if PtrUInt(DynArray)and 7<>0 then inc(DynArray,8-(PtrUInt(DynArray)and 7)); {$endif} end; aWriter.CancelLastComma; aWriter.Add(']'); dec(aWriter.fHumanReadableLevel); end; ptRecord: begin Prop.WriteOneLevel(aWriter,Value,Options); aWriter.Add(','); exit; end; ptCustom: TJSONCustomParserCustom(Prop).CustomWriter(aWriter,Value^); end; aWriter.Add(','); inc(Value,Prop.fDataSize); end; var i: integer; SubProp: TJSONCustomParserRTTI; begin if P=nil then begin aWriter.AddShort('null'); ................................................................................ SubProp := NestedProperty[i]; if soWriteHumanReadable in Options then aWriter.AddCRAndIndent; aWriter.AddFieldName(SubProp.PropertyName); if soWriteHumanReadable in Options then aWriter.Add(' '); WriteOneValue(SubProp,P); end; aWriter.CancelLastComma; dec(aWriter.fHumanReadableLevel); if soWriteHumanReadable in Options then aWriter.AddCRAndIndent; aWriter.Add('}'); end; |
> | | > | > > | | | | > | | | | | | < < < > |
5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 ..... 30137 30138 30139 30140 30141 30142 30143 30144 30145 30146 30147 30148 30149 30150 30151 ..... 31514 31515 31516 31517 31518 31519 31520 31521 31522 31523 31524 31525 31526 31527 31528 31529 31530 31531 31532 31533 31534 31535 31536 31537 31538 31539 ..... 31544 31545 31546 31547 31548 31549 31550 31551 31552 31553 31554 31555 31556 31557 31558 31559 31560 ..... 31568 31569 31570 31571 31572 31573 31574 31575 31576 31577 31578 31579 31580 31581 31582 31583 ..... 31609 31610 31611 31612 31613 31614 31615 31616 31617 31618 31619 31620 31621 31622 31623 31624 31625 31626 31627 ..... 32288 32289 32290 32291 32292 32293 32294 32295 32296 32297 32298 32299 32300 32301 32302 32303 32304 32305 32306 32307 32308 32309 32310 32311 32312 32313 32314 32315 32316 32317 32318 32319 32320 ..... 32330 32331 32332 32333 32334 32335 32336 32337 32338 32339 32340 32341 32342 32343 32344 |
// - to be called if TypeNameToSimpleRTTIType() did fail, i.e. return ptCustom // - will return ptCustom for any unknown type class function TypeInfoToSimpleRTTIType(Info: pointer; ItemSize: integer): TJSONCustomParserRTTIType; /// unserialize some JSON content into its binary internal representation function ReadOneLevel(var P: PUTF8Char; var Data: PByte; Options: TJSONCustomParserSerializationOptions): boolean; virtual; /// serialize a binary internal representation into JSON content // - this method won't append a trailing ',' character procedure WriteOneLevel(aWriter: TTextWriter; var P: PByte; Options: TJSONCustomParserSerializationOptions); virtual; /// the associated type name, e.g. for a record property CustomTypeName: RawUTF8 read fCustomTypeName; /// the property name // - may be void for the Root element // - e.g. 'SubProp' ................................................................................ asm // faster version by AB (direct call to finalization procedures) { -> EAX pointer to record to be finalized } { EDX pointer to type info } { <- EAX pointer to record to be finalized } movzx ecx,byte ptr [edx].TFieldTable.NameLen push ebx mov ebx,eax push esi push edi mov edi,[edx+ecx].TFieldTable.ManagedCount lea esi,[edx+ecx].TFieldTable.ManagedFields test edi,edi jz @@end @@loop: mov edx,[esi].TFieldInfo.TypeInfo mov eax,[esi].TFieldInfo.&Offset ................................................................................ begin inherited; fNestedArray.Free; end; procedure TJSONCustomParserCustomSimple.CustomWriter( const aWriter: TTextWriter; const aValue); var i: integer; i64: Int64; V: PByte; begin case fKnownType of ktStaticArray: begin aWriter.Add('['); V := @aValue; for i := 1 to PArrayTypeInfo(fTypeData)^.elCount do begin fNestedArray.WriteOneLevel(aWriter,V,[]); aWriter.Add(','); end; aWriter.CancelLastComma; aWriter.Add(']'); end; (* max: integer; item: PShortString; ktSet: begin // written as an object with set names as fields = true/false aWriter.Add('{'); item := GetEnumBaseTypeList(fTypeData,max); ................................................................................ inc(PByte(item),ord(item^[0])+1); // next short string end; aWriter.CancelLastComma; aWriter.Add('}'); end; *) ktEnumeration, ktSet: begin i64 := 0; MoveFast(aValue,i64,fDataSize); aWriter.Add(i64); // storing the value as binary/integer is safe and fast //aWriter.AddShort(GetEnumName(fCustomTypeInfo,byte(aValue))^); end; ktDynamicArray: raise ESynException.CreateUTF8('%.CustomWriter("%"): Unsupported', [self,fCustomTypeName]); else begin // encoded as JSON strings aWriter.Add('"'); ................................................................................ end; end; end; function TJSONCustomParserCustomSimple.CustomReader(P: PUTF8Char; var aValue; out EndOfObject: AnsiChar): PUTF8Char; var PropValue: PUTF8Char; i: integer; i64: Int64; wasString: boolean; Val: PByte; begin result := nil; // indicates error case fKnownType of ktStaticArray: begin if P^<>'[' then ................................................................................ if wasString and (TextToGUID(PropValue,@aValue)<>nil) then result := P; ktSet,ktEnumeration: begin if wasString then if fKnownType=ktSet then raise ESynException.CreateUTF8('%.CustomReader("%") not implemented yet from string', [self,fCustomTypeName]) else i64 := GetEnumNameValue(fCustomTypeInfo,PropValue,StrLen(PropValue)) else i64 := GetInt64(PropValue); if i64<0 then exit; MoveFast(i64,aValue,fDataSize); result := P; end; ktFixedArray: if wasString and (StrLen(PropValue)=fFixedSize*2) and SynCommons.HexToBin(PAnsiChar(PropValue),@aValue,fFixedSize) then result := P; end; ................................................................................ inc(aWriter.fHumanReadableLevel); DynArray := PPointer(Value)^; if DynArray<>nil then for j := 1 to DynArrayLength(DynArray) do begin if soWriteHumanReadable in Options then aWriter.AddCRAndIndent; if Prop.NestedProperty[0].PropertyName='' then // array of simple WriteOneValue(Prop.NestedProperty[0],DynArray) else Prop.WriteOneLevel(aWriter,DynArray,Options); // array of record aWriter.Add(','); {$ifdef ALIGNCUSTOMREC} if PtrUInt(DynArray)and 7<>0 then inc(DynArray,8-(PtrUInt(DynArray)and 7)); {$endif} end; aWriter.CancelLastComma; aWriter.Add(']'); dec(aWriter.fHumanReadableLevel); end; ptRecord: begin Prop.WriteOneLevel(aWriter,Value,Options); exit; end; ptCustom: TJSONCustomParserCustom(Prop).CustomWriter(aWriter,Value^); end; inc(Value,Prop.fDataSize); end; var i: integer; SubProp: TJSONCustomParserRTTI; begin if P=nil then begin aWriter.AddShort('null'); ................................................................................ SubProp := NestedProperty[i]; if soWriteHumanReadable in Options then aWriter.AddCRAndIndent; aWriter.AddFieldName(SubProp.PropertyName); if soWriteHumanReadable in Options then aWriter.Add(' '); WriteOneValue(SubProp,P); aWriter.Add(','); end; aWriter.CancelLastComma; dec(aWriter.fHumanReadableLevel); if soWriteHumanReadable in Options then aWriter.AddCRAndIndent; aWriter.Add('}'); end; |
Changes to SynopseCommit.inc.
1 |
'1.18.1974'
|
| |
1 |
'1.18.1975'
|