Smart questions
Smart answers
Smart people
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Member Login

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips now!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

Join Tek-Tips
*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

LINK TO THIS FORUM!

Add Stickiness To Your Site By Linking To This Professionally Managed Technical Forum.
Just copy and paste the
code below into your site.

Partner With Us!

"Best Of Breed" Forums Add Stickiness To Your Site
Partner Button
(Download This Button Today!)

Feedback

"...I can't start my day without this site!..."

Geography

Where in the world do Tek-Tips members come from?

Microsoft: Visual FoxPro FAQ

Classes and Objects

How can I save an object's properties (serialize), then restore them later (deserialize)?
Posted: 16 Jun 05

Serializing an object simply means taking its properites and storing them in a string (a serial, or linear, state), that can be later restored into a property-based object.

While objects can contain other objects, this greatly complicates the serialization/deserializing process.  This code only supports objects that don't contain other objects.

_ACCESS and _ASSIGN methods can also become problematic.

CODE

USE anyTable
SCATTER NAME oRec MEMO
cRec = serializeobject(oRec)
* do anything with the character data cRec...
*  ...say store it in a text file,
*  ...or send it through an email
*  ...or send it through TCP/IP
*  ...or pass it across a COM boundary
*  ...or, well, you get the picture!

oNewRec = deserializeobject(cRec)

* now examine oNewRec in the Debug Watch Window to see that it resembles oRec!


PROCEDURE SerializeObject
LPARAMETERS toObj
* Written by William GC Steinford
*  Input: toObj is a subclass of Empty (or a SCATTER NAME object)
* Output: a string representing toObj
LOCAL lnMem, laMem[1], lcOut, lcProp, lvData, lnI
lnMem = AMEMBERS(laMem,toObj,0)
SET TEXTMERGE TO MEMVAR lcOut ON
\\<? version="1.0" encoding="UTF-8" ?>
\<object class="empty">
FOR lnI = 1 TO lnMem
  lcProp = laMem[lnI]
  \  <property name="<<laMem[lnI]>>"
  lvData = EVALUATE('toObj.'+lcProp)
  * from lexRegistry.AnyTypeToC
  do case
    case varType(lvData)='T'
      \\ type="DATETIME">
      if empty(lvData)       
        \\{/:}
      ELSE
        lcData = "{^" + Transform(Year(  lvData)) + '/' ;
                      + Transform(Month( lvData)) + '/' ;
                      + Transform(Day(   lvData)) + ' ' ;
                      + Transform(hour(  lvData)) + ':' ;
                      + Transform(Minute(lvData)) + ':' ;
                      + Transform(Sec(   lvData)) ;
                      + '}'
        \\<<lcData>>
      endif
    case varType(lvData)='D'
      \\ type="DATE">
      if EMPTY(lvData)
        \\{}
      else
        lcData = '{^ '+ alltrim(Str(Year(lvData))) + '/' ;
                      + alltrim(Str(Month(lvData))) + '/' ;
                      + alltrim(Str(Day(lvData))) + '}'
        \\<<lcData>>
      endif
    case varType(lvData)='L'
      \\ type="LOGICAL"><<iif( vData, '.T.', '.F.' )>>
    case varType(lvData)='N'
      \\ type="NUMERIC"><<Transform(lvData)>>
    case varType(lvData)='C'
      \\ type="CHARACTER">
      * UrlEncode dangerous characters:
      lcData = StrTran(lvData,'%',    '%25')
      lcData = StrTran(lcData,'"',    '%22')
      lcData = StrTran(lcData,['],    '%27')
      lcData = StrTran(lcData,'[',    '%5B')
      lcData = StrTran(lcData,']',    '%5D')
      lcData = StrTran(lcData,'<',    '%3C')
      lcData = StrTran(lcData,'>',    '%3E')
      lcData = StrTran(lcData,chr(13),'%0D')
      lcData = StrTran(lcData,chr(10),'%0A')
      \\<<lcData>>
    case varType(lvData)='O'
      * Skip sub objects.
      * We could recursively call SerializeObject to package this member.
  endcase  
  \\</property>
ENDFOR
\</object>
SET TEXTMERGE TO
RETURN lcOut

PROCEDURE DeSerializeObject
LPARAMETERS tcObj
* Written by William GC Steinford
*  Input: tcObj is a string representing a subclass of Empty (or a SCATTER NAME object)
* Output: an actual object representing tcObj
* Example tcObj Value:
*  <? version="1.0" encoding="UTF-8" ?>
*  <object class="empty">
*    <property name="TEXT" type="CHARACTER">There     </property>
*    <property name="TEXT2" type="CHARACTER"></property>
*  </object>
*
LOCAL lnProp, laProp[1], lcObj, lnStrt, lnStop, loOut, lnI
lnStrt = ATC('<property',  tcObj )
lnStop = RATC('</object>', tcObj )
lcObj  = SUBSTR( tcObj, lnStrt, lnStop-lnStrt )
lnProp = ALINES(laProp, STRTRAN(lcObj,'</property>',CHR(13)) )
loOut  = CREATEOBJECT('Empty')
FOR lnI = 1 TO lnProp
  lvVal  = .NULL.
  lcName = .NULL.
  TRY
    lcType = UPPER( SUBSTR(laProp[lnI], ATC('type="',laProp[lnI])+6) )
    lcName =        SUBSTR(laProp[lnI], ATC('name="',laProp[lnI])+6)
    IF NOT '"'$lcName
      lcName = .NULL.
      THROW "bad name"
    ENDIF
    lcName = LEFT(lcName,AT('"',lcName)-1)
    lcVal  =        SUBSTR(laProp[lnI], ATC('>',     laProp[lnI])+1)
    DO CASE
      CASE lcType='DATETIME' AND TYPE(lcVal)='T'
        lvVal = EVALUATE(lcVal)
      CASE lcType='C'        AND TYPE('['+lcVal+']')='C'
        lvVal = EVALUATE('['+lcVal+']')
      CASE TYPE(lcVal)=LEFT(lcType,1)
        lvVal = EVALUATE(lcVal)
    ENDCASE
  CATCH TO oExc
    * Ignore errors... lvVal=.NULL. will signify errors.
  ENDTRY
  
  IF NOT ISNULL(lcName)
    TRY
      ADDPROPERTY(loOut, lcName, lvVal)
    CATCH TO oExc
      * Ignore errors
    ENDTRY
  ENDIF
ENDFOR
RETURN loOut

Back to Microsoft: Visual FoxPro FAQ Index
Back to Microsoft: Visual FoxPro Forum

My Archive

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close