Serialize, Mapping, Bears OH! MY!

Serialize, Mapping, Bears OH! MY!

These two WL features may be the poorest documented features in WL. Go ahead I dare you to go find the doucumentation for either one. But never fear Uncle Pete is going to take a few minutes to give you a few pointers.

Serialize

Let’s talk about Serialize first. The first issue is Serialize is both a function and an attribute. You know sort of like being both a noun and a verb 🙂 And when you go searching through the docs you are going to mainly find this page.

In simple terms, the Serialize function converts complex data from one type to another. For the purposes of our conversation, we are mainly concerned about moving structure and class data to and from XML and JSON. And at this point, unless I am absolutely forced to I really only deal with JSON data. So today’s talk we will assume we are talking about moving data between a complex WL variable to JSON data. The WL complex data I am talking about is either an array of Classes or an array of structures. For this purpose there isn’t really much of a difference between classes and structures, and in grossly oversimplified turns we can say a class is just a “smart” structure because it can have methods and properties. We will explore how this difference affects serialization in a bit.

Although this talk is specifically about serialization and mapping, many of you may have already guessed the underlining reason for the article is the wxFileManager, which at the end of the day is just a really fancy class that manages arrays. The version we are currently working on is REALLY REALLY fancy, but that talk isn’t for today 🙂

Where we really start dealing with Serialization is with web services, we want to send our complex data to a web service or retrieve complex data from a web service. That will hopefully be done via a RESTful service and JSON data. If you are really unlucky it will be a SOAP service and XML data. So Serializing our data is required.

The first half of the help page I linked to above covers the user of the Serialize function to do this. A quick example would be:

	arrCashier is array of Cashier
	jsonCashier is JSON 
	Serialize(arrCashier,jsonCashier,psdJSON)

And just like that, we have moved our array of Cashier record classes into JSON data. Simple and easy right? Well, guess what I haven’t used the Serialize function in forever, because a few versions ago PCSOFT gave us automatic serialization. So my code actually looks like this:

	arrCashier is array of Cashier
	jsonCashier is JSON 
	jsonCashier <= arrCashier

That <= is the assignment by copy operator BTW, and if you are using it you are missing out! But again a topic for another day 🙂

So the first confusing thing about Serialize is although I am Serializing my data, you don’t actually find the Serialize function in my code. The good news is even though I am not using the function, the other features of serialization are still supported with automatic serialization. What functions am I talking about? Scroll down to the bottom of that help page linked above and you will see a heading titled Serializing the members of classes and structures.

The first feature we find out about in that section is how to prevent a member from being serialized.

Say my Cashier class looked like this. It doesn’t but say it does 🙂

Cashier is a Class
	ID is int
	CashierCode is string
	Name is string
END

Perhaps when I don’t want to include ID in the JSON when I send the records out via my web service, how would I do that? I would use the serialize attribute to tell it not to serialize that member. My class code would look like this

Cashier is a Class
	ID is int,serialize=false
	CashierCode is string
	Name is string
END

And now my resulting JSON data would only have CashierCode and Name in it. But wait there’s more! What if I want CashierCode to be called Code in the JSON data? Then my class would look like this:

Cashier is a Class
	ID is int,serialize=false
	CashierCode is string,serialize="Code"
	Name is string
END

And now my JSON data would have Code and Name in it. Pretty cool, right? So now let’s look at a bit more complex of an example. We often have much more complex data than that, with arrays inside of the record. I prime example might be Invoice and InvoiceLine. So let’s look at a simple example of those classes

InvoiceLine is Class
	ID is int
	ProductID is int
END
Invoice is a Class
	ID is int
	VendorID is int
	InvoiceDate is date
	arrLines is array of InvoiceLine
END

In this example, arrLines is an array containing our lines. Or naming convention is to prefix arrays with arr, so we know we are dealing with the array instead of a single record (rec). But we want the outside world to see Lines, not arrLines. No problem you think (and so did I), we just write the line like so:

arrLines is array of InvoiceLine,serialize="Lines"

WRONG! And this is what prompted this article. This generates a compile error. We tried various things, but since we were under some deadlines, we just moved on and submitted the question to support. I got back a message that was partially in French and partially in English, but consulting my handy Frenglish dictionary I was able to deduce the answer. The code gets written like this:

arrLines is array <serialize="Lines"> of InvoiceLine

Because we are renaming the array or attribute has to be on the array definition portion of the declaration. I am not sure I totally agree with that, but if that’s the way the compiler wants it that’s the way I will do it 🙂 So now our JSON data has an array of Lines inside each Invoice.

Before moving on to Mapping there is one last thing I should mention about Serialize and that has to do with the difference between classes and structures. In the example above I showed an array of InvoiceLine record classes, but in reality we normally just have our manager class declared instead, and because of the complex nature of the manager class, with dynamic data and inheritance, it generates an error when you attempt to serialize it, so for use the Invoice Class would normally look like so:

Invoice is a Class
	ID is int
	VendorID is int
	InvoiceDate is date
	mgrInvoiceLine is wxManagerClass,serialize=false
END

Which prevents serialize from attempting to serialize the manager class.

Mapping

If you think finding the help for the Serialize attribute was tough, I double dog dare you to find the help for Mapping. Go ahead I will wait 🙂 You give up yet? Go over to the Assigment operators help page, scroll down, and under the Homonymic Copy section, you will see the mapping attribute in use! Think of the mapping attribute as the exact opposite of the serialize attribute. Mapping is used to map a member to a different name so when the Copy by Assignment or is that Homonymic Copy (I guess it depends on which help page you read!) takes place it uses an alternative name to the actual variable name to match the member and place data in it.

Back to our Cashier example, perhaps I have some JSON data that I want to move into my Cashier array, however, in this JSON data the Name is called CashierName. If I add a mapping attribute then CashierName from the JSON data will get into the Name field in my array. So now my class looks like this:

Cashier is a Class
	ID is int,serialize=false
	CashierCode is string,serialize="Code"
	Name is string,mapping="CashierName"
END

That is really all there is to Mapping, once you understand Serialize, the Mapping attribute makes sense.

Bringing it all together!

You know this wouldn’t be an Uncle Pete article without some bonus material, now would it. Back to our Invoice example. We want the outside world to see the array of lines as Lines, however, we want to call it arrLines. We solved that with the Serialize attribute. But now what happens if the outside world also needs to send us lines? Well if they send us an array called Lines it isn’t going to match up with arrLines, so we need to also do the Mapping attribute. But now the challenge is how to include both attributes on one line. I am going to just cut to the chase and save you the trouble of fighting with it and point you to a little blurb at the bottom of this help page. And now finally our arrLines declaration looks like so

arrLines is array <serialize="Lines",mapping="Lines"> of InvoiceLine

And now we get to use arrLines in all of our code and get along perfectly fine with the outside world which thinks it is called Lines.

That’s it for today! We are really busy on a new project, but I promise you there are some cool things on the horizon. We have added a couple of new features to the File Manager which has allowed us to change how we define and use some of our joins and lookups, making the classes even more efficient to use. If you are an SQL fan you are really going to love this enhancement!

We have also create a completely new extension class called the Rest Manager, which allows you to very quickly convert your File Manager enabled project into having a complete RESTful web service backend, and making all your data calls from your client code via REST, with almost zero changes to your client code!

But wait there is even more! The Default Manager has also been completely revamped into the Setting Manager which is fully File Manager and Rest Manager aware, and stores the data in JSON format, allowing direct mapping to screen controls, etc. The config file portion of the Default Manager becomes its own Config Manager, making it simpler to create and use standard XML config files in your application, without the need for the rest of the Default management if you don’t need it.

All of this is being integrated into a very large production system that is keeping us very busy, but we will get the new features and classes documented and released as soon as possible

Leave a comment