In Dynamics 365 Finance & Operations (D365 F&O), we often work with Map objects to store key-value pairs. But what happens when the values are objects — like custom classes — and you want to persist or transfer the map?
X++ gives us Map.pack() and Map::create() methods to help serialize and deserialize maps, but when your map contains objects as values, there's a catch!
By default, X++ containers (used behind the scenes in pack()) do not support object types like class instances or records.
So when you try this:
Map myMap = new Map(Types::String, Types::Class);
and insert a class object as the value, the pack() method won’t work unless your class implements:
pack() method — to convert object state into a container.create() method — to restore object state from the container.Let’s define a custom class that will be used as a map value:
class MyData
{
int amount;
str description;
public void new(int _amount, str _desc)
{
amount = _amount;
description = _desc;
}
public container pack()
{
return [amount, description];
}
public static MyData create(container _c)
{
int amount = conPeek(_c, 1);
str description = conPeek(_c, 2);
return new MyData(amount, description);
}
public str toString()
{
return strFmt("Amount: %1, Desc: %2", amount, description);
}
}
Here’s a simple job that:
MyData objects.Map::create()
internal final class Job_MapCreateFromContainerExample
{
/// <summary>
/// Class entry point. The system will call this method when a designated menu
/// is selected or when execution starts and this class is set as the startup class.
/// </summary>
/// <param name = "_args">The specified arguments.</param>
public static void main(Args _args)
{
Map mapOriginal = new Map(Types::String, Types::Class);
Map mapRestored;
container packedMap;
str key = "Item1";
MyData data1 = new MyData(100, "Test object");
// Insert object into map
mapOriginal.insert(key, data1);
// Pack the map into a container
packedMap = mapOriginal.pack();
// Recreate the map from packed container
mapRestored = Map::create(packedMap);
// Lookup the object from restored map
MyData restoredData = mapRestored.lookup(key);
// Print both
info("Original: " + data1.toString());
info("Restored: " + restoredData.toString());
}
}
pack() and create() in your custom classes to serialize/deserialize.Using Map.pack() and Map::create() with objects in X++ isn't difficult once you understand how packing works. Just make sure every object in the map (whether key or value) knows how to serialize and deserialize itself using pack() and create() methods.
Happy coding in Dynamics 365 F&O! 🚀