serialization: Use Cereal NVP

This commit modifies the serialization APIs to start utilizing
Cereal's name-value pair (NVP) feature to store to and load from
the JSONs where the interface data is persisted.

Using NVP enables us to add/remove properties to interfaces
without breaking de-serialization.

Since we need to be able to handle both old mechanism of not
using NVP as well as the new one, this commit also bumps up the
Cereal class version to 2 by default. The load functions then look
at the version to decide how best to load the object. The save
functions always store with NVP.

Tested:
Verified the serialized JSONs contained NVP type data.
Verified that the new code is still able to load the
old JSONs.

Signed-off-by: Santosh Puranik <santosh.puranik@in.ibm.com>
Change-Id: I583b842b8aaa23ee61bb98fdcd5a20d718163be6
diff --git a/configure.ac b/configure.ac
index 096b8bd..1f33112 100644
--- a/configure.ac
+++ b/configure.ac
@@ -108,7 +108,7 @@
     [Path of associations JSON file])
 
 AC_ARG_VAR(CLASS_VERSION, [Class version to register with Cereal])
-AS_IF([test "x$CLASS_VERSION" == "x"], [CLASS_VERSION=1])
+AS_IF([test "x$CLASS_VERSION" == "x"], [CLASS_VERSION=2])
 AC_DEFINE_UNQUOTED([CLASS_VERSION], [$CLASS_VERSION], [Class version to register with Cereal])
 
 # Create configured output
diff --git a/gen_serialization.mako.hpp b/gen_serialization.mako.hpp
index bae2d33..b4d9568 100644
--- a/gen_serialization.mako.hpp
+++ b/gen_serialization.mako.hpp
@@ -22,6 +22,8 @@
 static constexpr auto skipSignals = true;
 namespace cereal
 {
+// The version we started using cereal NVP from
+static constexpr size_t CLASS_VERSION_WITH_NVP = 2;
 
 % for iface in interfaces:
 <% properties = interface_composite.names(str(iface)) %>\
@@ -30,14 +32,13 @@
           const ${iface.namespace()}& object,
           const std::uint32_t version)
 {
-<%
-    props = ["object." + p.camelCase + "()" for p in properties]
-    props = ', '.join(props)
+% for p in properties:
+<% t = "cereal::make_nvp(\"" + p.CamelCase + "\", object." + p.camelCase + "())"
 %>\
-    a(${props});
+        a(${t});
+% endfor
 }
 
-
 template<class Archive>
 void load(Archive& a,
           ${iface.namespace()}& object,
@@ -47,10 +48,27 @@
 <% t = "object." + p.camelCase + "()" %>\
     decltype(${t}) ${p.CamelCase}{};
 % endfor
+    if (version < CLASS_VERSION_WITH_NVP)
+    {
 <%
     props = ', '.join([p.CamelCase for p in properties])
 %>\
-    a(${props});
+        a(${props});
+    }
+    else
+    {
+% for p in properties:
+<% t = "cereal::make_nvp(\"" + p.CamelCase + "\", " + p.CamelCase + ")" %>\
+        try
+        {
+            a(${t});
+        }
+        catch (Exception &e)
+        {
+            // Ignore any exceptions, property value stays default
+        }
+% endfor
+    }
 % for p in properties:
 <% t = "object." + p.camelCase + "(" + p.CamelCase + ", skipSignals)" %>\
     ${t};