Skip to content

Commit abb1ece

Browse files
authored
Merge pull request #141 from rschlaikjer/rs-support-unordered-map
Add support for unordered_map, deque JSON Ser/Des
2 parents 86af19b + 0563e0a commit abb1ece

File tree

1 file changed

+69
-4
lines changed

1 file changed

+69
-4
lines changed

include/mujincontrollerclient/mujinjson.h

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
#include <string>
2828
#include <stdexcept>
2929
#include <vector>
30+
#include <unordered_map>
3031
#include <map>
32+
#include <deque>
3133
#include <iostream>
3234

3335
#include <rapidjson/pointer.h>
@@ -206,7 +208,7 @@ inline void ParseJson(rapidjson::Value& r, rapidjson::Document::AllocatorType& a
206208
throw MujinJSONException(boost::str(boost::format("Json stream is invalid (offset %u) %s")%((unsigned)rTemp.GetErrorOffset())%GetParseError_En(rTemp.GetParseError())));
207209
}
208210
r.Swap(rTemp);
209-
211+
210212
// rapidjson::ParseResult parseResult = reader.template Parse<rapidjson::kParseFullPrecisionFlag>(isw, rTemp);
211213
// if( parseResult.IsError() ) {
212214
// *stack_.template Pop<ValueType>(1)
@@ -490,17 +492,60 @@ template<class U> inline void LoadJsonValue(const rapidjson::Value& v, std::map<
490492
}
491493
} else if (v.IsObject()) {
492494
t.clear();
493-
U value;
494495
for (rapidjson::Value::ConstMemberIterator it = v.MemberBegin();
495496
it != v.MemberEnd(); ++it) {
496-
LoadJsonValue(it->value, value);
497-
t[std::string(it->name.GetString(), it->name.GetStringLength())] = value; // string can contain null character
497+
// Deserialize directly into the map to avoid copying temporaries.
498+
// Note that our key needs to be explicitly length-constructed since
499+
// it may contain \0 bytes.
500+
LoadJsonValue(it->value,
501+
t[std::string(it->name.GetString(),
502+
it->name.GetStringLength())]);
498503
}
499504
} else {
500505
throw MujinJSONException("Cannot convert json type " + GetJsonTypeName(v) + " to Map");
501506
}
502507
}
503508

509+
template<class U> inline void LoadJsonValue(const rapidjson::Value& v, std::deque<U>& t) {
510+
// It doesn't make sense to construct a deque from anything other than a JSON array
511+
if (!v.IsArray()) {
512+
throw MujinJSONException("Cannot convert json type " + GetJsonTypeName(v) + " to deque");
513+
}
514+
515+
// Ensure our output is a blank slate
516+
t.clear();
517+
518+
// Preallocate to fit the incoming data. Deque has no reserve, only resize.
519+
t.resize(v.Size());
520+
521+
// Iterate each array entry and attempt to deserialize it directly as a member type
522+
typename std::deque<U>::size_type emplaceIndex = 0;
523+
for (rapidjson::Value::ConstValueIterator it = v.Begin(); it != v.End(); ++it) {
524+
// Deserialize directly into the map to avoid copying temporaries.
525+
LoadJsonValue(*it, t[emplaceIndex++]);
526+
}
527+
}
528+
529+
template<class U> inline void LoadJsonValue(const rapidjson::Value& v, std::unordered_map<std::string, U>& t) {
530+
// It doesn't make sense to construct an unordered map from anything other
531+
// than a full JSON object
532+
if (!v.IsObject()) {
533+
throw MujinJSONException("Cannot convert json type " + GetJsonTypeName(v) + " to unordered_map");
534+
}
535+
536+
// Ensure our output is a blank slate
537+
t.clear();
538+
for (rapidjson::Value::ConstMemberIterator it = v.MemberBegin();
539+
it != v.MemberEnd(); ++it) {
540+
// Deserialize directly into the map to avoid copying temporaries.
541+
// Note that our key needs to be explicitly length-constructed since it
542+
// may contain \0 bytes.
543+
LoadJsonValue(
544+
it->value,
545+
t[std::string(it->name.GetString(), it->name.GetStringLength())]);
546+
}
547+
}
548+
504549
//Save a data structure to rapidjson::Value format
505550

506551
/*template<class T> inline void SaveJsonValue(rapidjson::Value& v, const T& t, rapidjson::Document::AllocatorType& alloc) {*/
@@ -650,6 +695,26 @@ template<class U> inline void SaveJsonValue(rapidjson::Value& v, const std::map<
650695
}
651696
}
652697

698+
template<class U> inline void SaveJsonValue(rapidjson::Value& v, const std::unordered_map<std::string, U>& t, rapidjson::Document::AllocatorType& alloc) {
699+
v.SetObject();
700+
for (typename std::unordered_map<std::string, U>::const_iterator it = t.begin(); it != t.end(); ++it) {
701+
rapidjson::Value name, value;
702+
SaveJsonValue(name, it->first, alloc);
703+
SaveJsonValue(value, it->second, alloc);
704+
v.AddMember(name, value, alloc);
705+
}
706+
}
707+
708+
template <class T, class AllocT> inline void SaveJsonValue(rapidjson::Value& v, const std::deque<T, AllocT>& t, rapidjson::Document::AllocatorType& alloc) {
709+
v.SetArray();
710+
v.Reserve(t.size(), alloc);
711+
for (typename std::deque<T, AllocT>::const_iterator it = t.begin(); it != t.end(); ++it) {
712+
rapidjson::Value value;
713+
SaveJsonValue(value, *it, alloc);
714+
v.PushBack(value, alloc);
715+
}
716+
}
717+
653718
template<class T> inline void SaveJsonValue(rapidjson::Document& v, const T& t) {
654719
// rapidjson::Value::CopyFrom also doesn't free up memory, need to clear memory
655720
// see note in: void ParseJson(rapidjson::Document& d, const std::string& str)

0 commit comments

Comments
 (0)