diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h b/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h
index a4d2f26f0a60dddbb399155989cb0bca2a9121f1..0c09880dfb743245b6f34749801c5c52fa4afe6a 100644
--- a/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h
@@ -254,10 +254,64 @@ IPAACA_HEADER_EXPORT class PayloadIterator//{{{
 };
 //}}}
 
+IPAACA_HEADER_EXPORT class PayloadEntryProxyMapIterator//{{{
+{
+	public:
+		typedef rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>::MemberIterator RawIterator;
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* proxy;
+		IPAACA_MEMBER_VAR_EXPORT RawIterator raw_iterator;
+	public:
+		IPAACA_HEADER_EXPORT PayloadEntryProxyMapIterator(PayloadEntryProxy* proxy, RawIterator&& raw_iter);
+		IPAACA_HEADER_EXPORT PayloadEntryProxyMapIterator& operator++();
+		IPAACA_HEADER_EXPORT std::pair<std::string, PayloadEntryProxy> operator*();
+		IPAACA_HEADER_EXPORT std::shared_ptr<std::pair<std::string, PayloadEntryProxy> > operator->();
+		IPAACA_HEADER_EXPORT bool operator==(const PayloadEntryProxyMapIterator& other_iter);
+		IPAACA_HEADER_EXPORT bool operator!=(const PayloadEntryProxyMapIterator& other_iter);
+};
+//}}}
+IPAACA_HEADER_EXPORT class PayloadEntryProxyListIterator//{{{
+{
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* proxy;
+		IPAACA_MEMBER_VAR_EXPORT size_t current_idx;
+		IPAACA_MEMBER_VAR_EXPORT size_t size;
+	public:
+		IPAACA_HEADER_EXPORT PayloadEntryProxyListIterator(PayloadEntryProxy* proxy, size_t idx, size_t size);
+		IPAACA_HEADER_EXPORT PayloadEntryProxyListIterator& operator++();
+		IPAACA_HEADER_EXPORT PayloadEntryProxy operator*();
+		IPAACA_HEADER_EXPORT std::shared_ptr<PayloadEntryProxy> operator->();
+		IPAACA_HEADER_EXPORT bool operator==(const PayloadEntryProxyListIterator& other_iter);
+		IPAACA_HEADER_EXPORT bool operator!=(const PayloadEntryProxyListIterator& other_iter);
+};
+//}}}
+IPAACA_HEADER_EXPORT class PayloadEntryProxyMapDecorator//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline PayloadEntryProxyMapDecorator(PayloadEntryProxy* proxy_): proxy(proxy_) { }
+		IPAACA_HEADER_EXPORT PayloadEntryProxyMapIterator begin();
+		IPAACA_HEADER_EXPORT PayloadEntryProxyMapIterator end();
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* proxy;
+};
+//}}}
+IPAACA_HEADER_EXPORT class PayloadEntryProxyListDecorator//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline PayloadEntryProxyListDecorator(PayloadEntryProxy* proxy_): proxy(proxy_) { }
+		IPAACA_HEADER_EXPORT PayloadEntryProxyListIterator begin();
+		IPAACA_HEADER_EXPORT PayloadEntryProxyListIterator end();
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* proxy;
+};
+//}}}
 IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
 {
 	friend std::ostream& operator<<(std::ostream& os, const PayloadEntryProxy& proxy);
 	protected:
+	public:
+		IPAACA_HEADER_EXPORT PayloadEntryProxyMapDecorator as_map();
+		IPAACA_HEADER_EXPORT PayloadEntryProxyListDecorator as_list();
 	public:
 		//IPAACA_MEMBER_VAR_EXPORT rapidjson::Document* _json_parent_node;
 		//IPAACA_MEMBER_VAR_EXPORT rapidjson::Document* _json_node;
@@ -283,6 +337,8 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
 		// constructors for navigation through objects
 		IPAACA_HEADER_EXPORT PayloadEntryProxy(PayloadEntryProxy* parent, const std::string& addressed_key);
 		IPAACA_HEADER_EXPORT PayloadEntryProxy(PayloadEntryProxy* parent, size_t addressed_index);
+	public:
+		IPAACA_HEADER_EXPORT size_t size();
 	public:
 		IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](size_t index); // array-style navigation
 		IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](int index); // int is UNFORTUNATELY required to catch
diff --git a/ipaacalib/cpp/src/ipaaca-json.cc b/ipaacalib/cpp/src/ipaaca-json.cc
index 3be11f627afce223d5134b36233329c89741f017..4124d3994f702e26c643398d522d1f8e01976de4 100644
--- a/ipaacalib/cpp/src/ipaaca-json.cc
+++ b/ipaacalib/cpp/src/ipaaca-json.cc
@@ -41,7 +41,20 @@ using namespace std;
 
 int iterators_main(int argc, char** argv)//{{{
 {
-	std::string json_source("[\"old\",2,3,{\"key1\":\"value1\", \"key2\":\"value2\"}]");
+	std::string json_source("[\n\
+	\"old\",\n\
+	[\n\
+		\"str\",\n\
+		null\n\
+	],\n\
+	3,\n\
+	{\n\
+		\"key1\": \"value1\",\n\
+		\"key2\": \"value2\"\n\
+	}\n\
+]");
+	
+	std::cout << "Using this JSON document as initial payload entry 'a':" << std::endl << json_source << std::endl;
 	ipaaca::PayloadDocumentEntry::ptr entry = ipaaca::PayloadDocumentEntry::from_json_string_representation(json_source);
 	
 	ipaaca::FakeIU::ptr iu = ipaaca::FakeIU::create();
@@ -50,14 +63,18 @@ int iterators_main(int argc, char** argv)//{{{
 	iu->payload()["bPrime"] = "simpleString";
 	iu->payload()["c"] = "anotherSimpleString";
 	iu->payload()["d"] = 100;
-	iu->payload()["e"] = 10000l;
+	iu->payload()["e"] = 3l;
 	
-	std::cout << "Iterate over payload" << std::endl;
+	std::cout << std::endl << "Iterate over payload" << std::endl;
 	for (auto it = iu->payload().begin(); it != iu->payload().end(); ++it) {
 		std::cout << "  " << it->first << " -> " << it->second << std::endl;
 	}
+	std::cout << std::endl << "Iterate over payload, range-based" << std::endl;
+	for (auto it: iu->payload()) {
+		std::cout << "  " << it.first << " -> " << it.second << std::endl;
+	}
 	
-	std::cout << "Comparisons" << std::endl;
+	std::cout << std::endl << "Comparisons" << std::endl;
 	bool eq;
 	eq = iu->payload()["a"] == iu->payload()["b"];
 	std::cout << "  a==b ? : " << (eq?"true":"false") << std::endl;
@@ -69,7 +86,57 @@ int iterators_main(int argc, char** argv)//{{{
 	std::cout << "  b==100 ? : " << (eq?"true":"false") << std::endl;
 	eq = iu->payload()["d"] == 100;
 	std::cout << "  d==100 ? : " << (eq?"true":"false") << std::endl;
-
+	eq = iu->payload()["a"][2] == iu->payload()["e"];
+	std::cout << "  a[2]==e ? : " << (eq?"true":"false") << std::endl;
+	
+	std::cout << std::endl << "Inner iterators, map (printing values as strings)" << std::endl;
+	try {
+		auto inner = iu->payload()["a"][3];
+		std::cout << "Map iteration over payload['a'][3], which equals " << inner << std::endl;
+		std::cout << "Reported size is " << inner.size() << std::endl;
+		for (auto kv: inner.as_map()) {
+			std::cout << "  \"" << kv.first << "\" -> \"" << kv.second << "\"" << std::endl;
+		}
+	} catch (ipaaca::Exception& ex) {
+		std::cout << "  Unexpected exception: " << ex.what() << std::endl;
+	}
+	try {
+		auto inner = iu->payload()["a"][2];
+		std::cout << "Map iteration over payload['a'][2], which equals " << inner << std::endl;
+		std::cout << "Reported size is " << inner.size() << std::endl;
+		for (auto kv: inner.as_map()) {
+			std::cout << "  \"" << kv.first << "\" -> \"" << kv.second << "\"" << std::endl;
+		}
+	} catch (ipaaca::PayloadTypeConversionError& ex) {
+		std::cout << "  Failed as expected with " << ex.what() << std::endl;
+	} catch (ipaaca::Exception& ex) {
+		std::cout << "  Unexpected exception: " << ex.what() << std::endl;
+	}
+	
+	std::cout << std::endl << "Inner iterators, list (printing values as strings)" << std::endl;
+	try {
+		auto inner = iu->payload()["a"][1];
+		std::cout << "List iteration over payload['a'][1], which equals " << inner << std::endl;
+		std::cout << "Reported size is " << inner.size() << std::endl;
+		for (auto proxy: inner.as_list()) {
+			std::cout << "  \"" << proxy << "\"" << std::endl;
+		}
+	} catch (ipaaca::Exception& ex) {
+		std::cout << "  Unexpected exception: " << ex.what() << std::endl;
+	}
+	try {
+		auto inner = iu->payload()["a"][1][1];
+		std::cout << "List iteration over payload['a'][1][1], which equals " << inner << std::endl;
+		std::cout << "Reported size is " << inner.size() << std::endl;
+		for (auto proxy: inner.as_list()) {
+			std::cout << "  \"" << proxy << "\"" << std::endl;
+		}
+	} catch (ipaaca::PayloadTypeConversionError& ex) {
+		std::cout << "  Failed as expected with " << ex.what() << std::endl;
+	} catch (ipaaca::Exception& ex) {
+		std::cout << "  Unexpected exception: " << ex.what() << std::endl;
+	}
+	
 	return 0;
 }
 //}}}
diff --git a/ipaacalib/cpp/src/ipaaca-payload.cc b/ipaacalib/cpp/src/ipaaca-payload.cc
index e8c6d145324449e62a21c5219c1ce203ef58bab7..99117e08cb87f44466e7bf69f708582c1b3aeb37 100644
--- a/ipaacalib/cpp/src/ipaaca-payload.cc
+++ b/ipaacalib/cpp/src/ipaaca-payload.cc
@@ -567,6 +567,25 @@ IPAACA_EXPORT bool PayloadEntryProxy::to_bool()
 	//return PayloadEntryProxy::get<bool>();
 }
 
+IPAACA_EXPORT PayloadEntryProxyMapDecorator PayloadEntryProxy::as_map()
+{
+	if (json_value && json_value->IsObject()) return PayloadEntryProxyMapDecorator(this);
+	throw PayloadTypeConversionError();
+}
+
+IPAACA_EXPORT PayloadEntryProxyListDecorator PayloadEntryProxy::as_list()
+{
+	if (json_value && json_value->IsArray()) return PayloadEntryProxyListDecorator(this);
+	throw PayloadTypeConversionError();
+}
+
+IPAACA_EXPORT size_t PayloadEntryProxy::size()
+{
+	if (!json_value) return 0;
+	if (json_value->IsArray()) return json_value->Size();
+	if (json_value->IsObject()) return json_value->MemberCount();
+	return 0;
+}
 
 //
 // new stuff for protocol v2
@@ -772,4 +791,90 @@ IPAACA_EXPORT bool PayloadIterator::operator!=(const PayloadIterator& ref)
 }
 //}}}
 
+// PayloadEntryProxyMapIterator//{{{
+IPAACA_EXPORT PayloadEntryProxyMapIterator::PayloadEntryProxyMapIterator(PayloadEntryProxy* proxy_, RawIterator&& raw_iter)
+: proxy(proxy_), raw_iterator(std::move(raw_iter))
+{
+}
+
+IPAACA_EXPORT PayloadEntryProxyMapIterator& PayloadEntryProxyMapIterator::operator++()
+{
+	// prevent increase beyond end() ?
+	raw_iterator++;
+	return *this;
+}
+
+IPAACA_EXPORT std::pair<std::string, PayloadEntryProxy> PayloadEntryProxyMapIterator::operator*()
+{
+	std::string key = raw_iterator->name.GetString();
+	return std::pair<std::string, PayloadEntryProxy>(key, (*proxy)[key] ); // generates child Proxy
+}
+
+IPAACA_EXPORT std::shared_ptr<std::pair<std::string, PayloadEntryProxy> > PayloadEntryProxyMapIterator::operator->()
+{
+	std::string key = raw_iterator->name.GetString();
+	return std::make_shared<std::pair<std::string, PayloadEntryProxy> >(key, (*proxy)[key] ); // generates child Proxy
+}
+IPAACA_EXPORT bool PayloadEntryProxyMapIterator::operator==(const PayloadEntryProxyMapIterator& other_iter)
+{
+	return raw_iterator==other_iter.raw_iterator;
+}
+IPAACA_EXPORT bool PayloadEntryProxyMapIterator::operator!=(const PayloadEntryProxyMapIterator& other_iter)
+{
+	return raw_iterator!=other_iter.raw_iterator;
+}
+//}}}
+// PayloadEntryProxyMapDecorator//{{{
+PayloadEntryProxyMapIterator PayloadEntryProxyMapDecorator::begin()
+{
+	return PayloadEntryProxyMapIterator(proxy, proxy->json_value->MemberBegin());
+}
+PayloadEntryProxyMapIterator PayloadEntryProxyMapDecorator::end()
+{
+	return PayloadEntryProxyMapIterator(proxy, proxy->json_value->MemberEnd());
+}
+//}}}
+
+// PayloadEntryProxyListIterator//{{{
+IPAACA_EXPORT PayloadEntryProxyListIterator::PayloadEntryProxyListIterator(PayloadEntryProxy* proxy_, size_t idx, size_t size_)
+: proxy(proxy_), current_idx(idx), size(size_)
+{
+}
+
+IPAACA_EXPORT PayloadEntryProxyListIterator& PayloadEntryProxyListIterator::operator++()
+{
+	if (current_idx!=size) current_idx++;
+	return *this;
+}
+
+IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxyListIterator::operator*()
+{
+	return (*proxy)[current_idx];
+}
+
+IPAACA_EXPORT std::shared_ptr<PayloadEntryProxy> PayloadEntryProxyListIterator::operator->()
+{
+	return std::make_shared<PayloadEntryProxy>((*proxy)[current_idx]);
+}
+IPAACA_EXPORT bool PayloadEntryProxyListIterator::operator==(const PayloadEntryProxyListIterator& other_iter)
+{
+	return (proxy==other_iter.proxy) && (current_idx==other_iter.current_idx);
+}
+IPAACA_EXPORT bool PayloadEntryProxyListIterator::operator!=(const PayloadEntryProxyListIterator& other_iter)
+{
+	return (current_idx!=other_iter.current_idx) || (proxy!=other_iter.proxy);
+}
+//}}}
+// PayloadEntryProxyListDecorator//{{{
+PayloadEntryProxyListIterator PayloadEntryProxyListDecorator::begin()
+{
+	return PayloadEntryProxyListIterator(proxy, 0, proxy->json_value->Size());
+}
+PayloadEntryProxyListIterator PayloadEntryProxyListDecorator::end()
+{
+	size_t size = proxy->json_value->Size();
+	return PayloadEntryProxyListIterator(proxy, size, size);
+}
+//}}}
+
 } // of namespace ipaaca