diff options
| author | Dan Goodliffe <dan@randomdan.homeip.net> | 2016-08-29 19:32:09 +0100 | 
|---|---|---|
| committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2016-08-29 19:32:09 +0100 | 
| commit | 0aec6119b0033aa0a67ad80c6c2658bc3f4e3285 (patch) | |
| tree | 39b8acecebff82b9aa7ddb7db1438edf785ecba9 | |
| parent | Change visibility and protection levels to allow inheritence from other libra... (diff) | |
| download | slicer-0aec6119b0033aa0a67ad80c6c2658bc3f4e3285.tar.bz2 slicer-0aec6119b0033aa0a67ad80c6c2658bc3f4e3285.tar.xz slicer-0aec6119b0033aa0a67ad80c6c2658bc3f4e3285.zip  | |
Add support for [de]serializing a dictionary as a json objectslicer-1.3.2
| -rw-r--r-- | slicer/json/serializer.cpp | 63 | ||||
| -rw-r--r-- | slicer/json/serializer.h | 1 | ||||
| -rw-r--r-- | slicer/test/initial/objectmap.json | 5 | ||||
| -rw-r--r-- | slicer/test/initial/objectmapMember.json | 8 | ||||
| -rw-r--r-- | slicer/test/preprocessor.cpp | 2 | ||||
| -rw-r--r-- | slicer/test/serializers.cpp | 26 | ||||
| -rw-r--r-- | slicer/test/types.ice | 9 | 
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;  | 
