summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2016-08-29 19:32:09 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2016-08-29 19:32:09 +0100
commit0aec6119b0033aa0a67ad80c6c2658bc3f4e3285 (patch)
tree39b8acecebff82b9aa7ddb7db1438edf785ecba9
parentChange visibility and protection levels to allow inheritence from other libra... (diff)
downloadslicer-1.3.2.tar.bz2
slicer-1.3.2.tar.xz
slicer-1.3.2.zip
Add support for [de]serializing a dictionary as a json objectslicer-1.3.2
-rw-r--r--slicer/json/serializer.cpp63
-rw-r--r--slicer/json/serializer.h1
-rw-r--r--slicer/test/initial/objectmap.json5
-rw-r--r--slicer/test/initial/objectmapMember.json8
-rw-r--r--slicer/test/preprocessor.cpp2
-rw-r--r--slicer/test/serializers.cpp26
-rw-r--r--slicer/test/types.ice9
7 files changed, 105 insertions, 9 deletions
diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp
index e50dd32..e6ddf81 100644
--- a/slicer/json/serializer.cpp
+++ b/slicer/json/serializer.cpp
@@ -1,4 +1,5 @@
#include "serializer.h"
+#include <slicer/metadata.h>
#include <jsonpp.h>
#include <boost/lexical_cast.hpp>
#include <boost/bind.hpp>
@@ -16,6 +17,10 @@ NAMEDFACTORY("application/json", Slicer::JsonStreamSerializer, Slicer::StreamSer
NAMEDFACTORY("application/json", Slicer::JsonStreamDeserializer, Slicer::StreamDeserializerFactory);
namespace Slicer {
+ const std::string md_object = "json:object";
+ const std::string keyName = "key";
+ const std::string valueName = "value";
+
class JsonValueSource : public ValueSource {
public:
JsonValueSource(const json::Value & s) :
@@ -144,15 +149,30 @@ namespace Slicer {
}
}
modelPart->Create();
- for (const auto & element : o) {
- auto emp = modelPart->GetChild(element.first);
- if (emp) {
+ if (metaDataFlagSet(modelPart->GetMetadata(), md_object)) {
+ for (const auto & element : o) {
+ auto emp = modelPart->GetAnonChild();
emp->Create();
- boost::apply_visitor(DocumentTreeIterate(emp), *element.second);
+ auto key = emp->GetChild(keyName);
+ auto value = emp->GetChild(valueName);
+ key->Create();
+ key->SetValue(new JsonValueSource(element.first));
+ key->Complete();
+ boost::apply_visitor(DocumentTreeIterate(value), *element.second);
emp->Complete();
}
}
- modelPart->Complete();
+ else {
+ for (const auto & element : o) {
+ auto emp = modelPart->GetChild(element.first);
+ if (emp) {
+ emp->Create();
+ boost::apply_visitor(DocumentTreeIterate(emp), *element.second);
+ emp->Complete();
+ }
+ }
+ modelPart->Complete();
+ }
}
void operator()(const json::Array & a) const
{
@@ -180,6 +200,20 @@ namespace Slicer {
}
void
+ JsonSerializer::ModelTreeIterateDictObj(json::Value * n, ModelPartPtr mp)
+ {
+ auto obj = boost::get<json::Object>(n);
+ json::Object::key_type k;
+ auto v = json::ValuePtr(new json::Value());
+ json::Value kv;
+ mp->GetChild(keyName)->GetValue(new JsonValueTarget(kv));
+ JsonValueSource s(kv);
+ s.set(k);
+ ModelTreeIterateRoot(v.get(), mp->GetChild(valueName));
+ obj->insert({ k, v });
+ }
+
+ void
JsonSerializer::ModelTreeIterate(json::Value * n, const std::string & name, ModelPartPtr mp)
{
if (name.empty() || !n) {
@@ -206,9 +240,16 @@ namespace Slicer {
break;
}
case mpt_Sequence:
- case mpt_Dictionary:
mp->OnEachChild(boost::bind(&JsonSerializer::ModelTreeIterateSeq, boost::get<json::Object>(*n).insert({name, json::ValuePtr(new json::Value(json::Array()))}).first->second.get(), _2));
break;
+ case mpt_Dictionary:
+ if (metaDataFlagSet(mp->GetMetadata(), md_object)) {
+ mp->OnEachChild(boost::bind(&JsonSerializer::ModelTreeIterateDictObj, boost::get<json::Object>(*n).insert({name, json::ValuePtr(new json::Value(json::Object()))}).first->second.get(), _2));
+ }
+ else {
+ mp->OnEachChild(boost::bind(&JsonSerializer::ModelTreeIterateSeq, boost::get<json::Object>(*n).insert({name, json::ValuePtr(new json::Value(json::Array()))}).first->second.get(), _2));
+ }
+ break;
}
}
}
@@ -239,8 +280,14 @@ namespace Slicer {
mp->OnEachChild(boost::bind(&JsonSerializer::ModelTreeIterateSeq, n, _2));
break;
case mpt_Dictionary:
- *n = json::Array();
- mp->OnEachChild(boost::bind(&JsonSerializer::ModelTreeIterate, n, _1, _2));
+ if (metaDataFlagSet(mp->GetMetadata(), md_object)) {
+ *n = json::Object();
+ mp->OnEachChild(boost::bind(&JsonSerializer::ModelTreeIterateDictObj, n, _2));
+ }
+ else {
+ *n = json::Array();
+ mp->OnEachChild(boost::bind(&JsonSerializer::ModelTreeIterate, n, _1, _2));
+ }
break;
}
}
diff --git a/slicer/json/serializer.h b/slicer/json/serializer.h
index c7e0fc3..cb83d16 100644
--- a/slicer/json/serializer.h
+++ b/slicer/json/serializer.h
@@ -9,6 +9,7 @@ namespace Slicer {
class JsonSerializer : public Serializer {
protected:
static void ModelTreeIterate(json::Value *, const std::string &, ModelPartPtr mp);
+ static void ModelTreeIterateDictObj(json::Value *, ModelPartPtr mp);
static void ModelTreeIterateSeq(json::Value *, ModelPartPtr mp);
static void ModelTreeIterateRoot(json::Value *, ModelPartPtr mp);
};
diff --git a/slicer/test/initial/objectmap.json b/slicer/test/initial/objectmap.json
new file mode 100644
index 0000000..c7e43ac
--- /dev/null
+++ b/slicer/test/initial/objectmap.json
@@ -0,0 +1,5 @@
+{
+ "one": 1,
+ "three hundred": 300,
+ "twenty": 20
+}
diff --git a/slicer/test/initial/objectmapMember.json b/slicer/test/initial/objectmapMember.json
new file mode 100644
index 0000000..c523899
--- /dev/null
+++ b/slicer/test/initial/objectmapMember.json
@@ -0,0 +1,8 @@
+{
+ "name": "foo",
+ "props": {
+ "one": 1,
+ "three hundred": 300,
+ "twenty": 20
+ }
+}
diff --git a/slicer/test/preprocessor.cpp b/slicer/test/preprocessor.cpp
index 18fad39..cc67d64 100644
--- a/slicer/test/preprocessor.cpp
+++ b/slicer/test/preprocessor.cpp
@@ -13,7 +13,7 @@
namespace fs = boost::filesystem;
-const unsigned int COMPONENTS_IN_TEST_ICE = 37;
+const unsigned int COMPONENTS_IN_TEST_ICE = 39;
BOOST_FIXTURE_TEST_SUITE ( preprocessor, FileStructure );
diff --git a/slicer/test/serializers.cpp b/slicer/test/serializers.cpp
index d23bd2f..95e8e87 100644
--- a/slicer/test/serializers.cpp
+++ b/slicer/test/serializers.cpp
@@ -249,6 +249,22 @@ checkSomeNumbers(const TestModule::SomeNumbers & sn)
BOOST_REQUIRE_EQUAL(sn, TestModule::FiftyFive);
}
+void
+checkObjectMap(const TestJson::Properties & p)
+{
+ BOOST_REQUIRE_EQUAL(3, p.size());
+ BOOST_REQUIRE_EQUAL(1, p.find("one")->second);
+ BOOST_REQUIRE_EQUAL(20, p.find("twenty")->second);
+ BOOST_REQUIRE_EQUAL(300, p.find("three hundred")->second);
+}
+
+void
+checkObjectMapMember(const TestJson::HasProperitiesPtr & p)
+{
+ BOOST_REQUIRE_EQUAL(p->name, "foo");
+ checkObjectMap(p->props);
+}
+
xmlpp::Document *
readXml(const fs::path & path)
{
@@ -422,6 +438,16 @@ BOOST_AUTO_TEST_CASE( json_rootEnums_json )
verifyByFile<TestModule::SomeNumbers, Slicer::JsonFileDeserializer>("enum2.json", checkSomeNumbers);
}
+BOOST_AUTO_TEST_CASE( json_objectmap )
+{
+ verifyByFile<TestJson::Properties, Slicer::JsonFileDeserializer>("objectmap.json", checkObjectMap);
+}
+
+BOOST_AUTO_TEST_CASE( json_objectmapMember )
+{
+ verifyByFile<TestJson::HasProperitiesPtr, Slicer::JsonFileDeserializer>("objectmapMember.json", checkObjectMapMember);
+}
+
BOOST_AUTO_TEST_CASE( json_streams )
{
const auto tmpf = tmp / "byStream";
diff --git a/slicer/test/types.ice b/slicer/test/types.ice
index b119df0..c2ac8f3 100644
--- a/slicer/test/types.ice
+++ b/slicer/test/types.ice
@@ -125,6 +125,15 @@ module TestModule {
};
};
+module TestJson {
+ [ "slicer:json:object" ]
+ dictionary<string, int> Properties;
+ class HasProperities {
+ string name;
+ Properties props;
+ };
+};
+
module TestModule2 {
class CrossModule extends TestModule::ClassType {
int anything;