Serializable class

Monkey Forums/Monkey Programming/Serializable class

Raul(Posted 2013) [#1]
It's first time when I actually need to make a serializable class. I searched the forums but I found just some references to Diddy framework. I would like to use it but I cannot find the download link for the last version :))

can anyone help me with that?


therevills(Posted 2013) [#2]
Google Code are dropping the download section very soon, so to get the latest version either use Hg or use the "zip" on the Google Code site:
https://code.google.com/p/diddy/source/browse/




Shinkiro1(Posted 2013) [#3]
I have written a reflection class, maybe that can help you.

Strict
Import reflection

#REFLECTION_FILTER += "framekit.object"


Class ReflectionObject Abstract
	
	Method ClassName:String() Property
		CacheClassInfo()
		Return SingleClassName(classInfo.Name)
	End
	
	Method SuperClassName:String() Property
		CacheClassInfo()
		Return SingleClassName(classInfo.SuperClass.Name)
	End
	
	Method InvokeMethod:Object(name:String, data:Object[] = [])
		CacheClassInfo()
		Local methods:= classInfo.GetMethods(False)
		For Local i:Int = 0 Until methods.Length
			Local m:MethodInfo = methods[i]
			If m.Name = name
				Return m.Invoke(Self, data)
			End
		Next
		Return Null
	End

	Method SetField:Void(name:String, value:Object)
		CacheClassInfo()
		Local f:= classInfo.GetField(name, False)
		If f
			f.SetValue(Self, value)
		End
	End
	
	Method FieldValue:Object(name:String)
		CacheClassInfo()
		Local f:= classInfo.GetField(name, False)
		If f
			Return f.GetValue(Self)
		End
		Return Null
	End
	
	Method FieldType:String(name:String)
		CacheClassInfo()
		Local f:= classInfo.GetField(name, False)
		If f
			Return SingleClassName(f.Type.Name)
		End
		Return ""
	End
	
	Method FieldNames:String[]()
		CacheClassInfo()
		Local fields:FieldInfo[] = classInfo.GetFields(False)
		Local fieldNames:String[fields.Length]
		For Local i:Int = 0 Until fields.Length
			fieldNames[i] = fields[i].Name
		End
		Return fieldNames
	End
	
	Private
	Method CacheClassInfo:Void()
		If Not classInfo
			classInfo = GetClass(Self)
		End
	End
	
	Field classInfo:ClassInfo
End

'input: a string with dot limited class names, e.g: monkey.lang.Object
'returns: only the last class name after the dot, e.g: Object
Function SingleClassName:String(classSignature:String)
	Local signature:String[] = classSignature.Split(".")
	Local last:Int = signature.Length - 1
	Return signature[last]
End


Obviously you need to extend ReflectionObject.


Raul(Posted 2013) [#4]
thanks, but now it's time for stupid questions.

I am using Diddy framework.

in the example I was you first serialize the object "tcSer", but when you desirializing it you are creating a new class tc2 but still using tcSer:

Print "Deserializing"
Local tc2:TestClass = TestClass(s.DeserializeObject(tcSer))
tcSer.Dispose()


I want to use this to save/load my game data. after I save/serialize it and I quit the game I no longer have that tcSer, so how can I access the savefile in this case?


Raul(Posted 2013) [#5]
still need some help here. I am sure it's simple but i cant figure it out and it's frustrating.

I have this class:

Class cGameLogic Implements ISerializable
	Global numberOfLogicScenes:Int
	Global logicScene:cLogicScene[]
	
	Global numberOfLogicMinigames:Int
	Global logicMinigame:cLogicScene[]
	
	Global numberOfLogicFlags:Int
	Global logicFlag:Int[]
			
	Global numberOfLogicInventoryObjects:Int
	Global logicInventoryObject:cLogicInventoryObject[]	
	Global invSlot:cInventorySlot[]
	
	Global numberOfLogicObjects:Int
	Global logicObject:cLogicObject[]
	
	Global objectInHand:Int
	Global isPlayingMinigame:Int
	Global previousSceneId:Int
	
	Method Serialize:Void(serializer:Serializer)
		serializer.Write("numberOfLogicScenes", numberOfLogicScenes)
		serializer.Write("numberOfLogicMinigames", numberOfLogicMinigames)
		serializer.Write("numberOfLogicFlags", numberOfLogicFlags)
	End	
	
	Method GetClassName:String()
		Return "cGameLogic"
	End
	
	Method GetGenericNames:String[]()
		Return []
	End

        'and here my class methods	


cant figure it out how exactly to save the file:

If KeyHit(KEY_1)
	Local saveSer:XMLElement = s.SerializeObject("savegame", cGlobals.myGameLogic)
	Print saveSer.ToString()
	EndIf


I assume I need to write the saveSer to a file, right??


Samah(Posted 2013) [#6]
The Diddy serialisation module was written before reflection was added to the language, and is very out of date. I would recommend using a solution like Shinkiro's until such time as I have time to rewrite the Diddy one.


Raul(Posted 2013) [#7]
I have no idea what reflection is {shame on me} and no clue how to use Shinkiro1's module :D


Gerry Quinn(Posted 2013) [#8]
I do it the old-fashioned way where every object has a Serialise function which in turn calls Serialise functions for its 'child' objects. Ultimately there are serialisation functions for Int, Bool and String. Store a version number as well if objects might change and you want to be able to load old save files.


Raul(Posted 2013) [#9]
in this case I can just save to a txt file all my data like:
from line 1 to 60 = inventory items
from line 61 to 160 = scene status
and so on..

and when I 'load' the game, i just read those variables, but I wanted to make it easier. in blitzmax was much funny


Shinkiro1(Posted 2013) [#10]
You can also use something like xml and not worry about line numbers.
It was easier in BlitzMax? Could you explain what you mean.


Raul(Posted 2013) [#11]
@Shinkiro1:
"It was easier in BlitzMax? Could you explain what you mean. "

well, there is a very smart guy there Brucey (i think we are all using his work), who made a module: persistence.

I simply save my class:

Local pers:TPersist = New TPersist			
Local stream:TStream = WriteStream(fileName)
pers.SerializeToStream(Globals.gameLogic, stream)			
stream.close()