Created
February 26, 2016 20:20
-
-
Save meetingcpp/060cfcfd3496883c4f40 to your computer and use it in GitHub Desktop.
Generic JSON Import - this code is accessing json via the json:: namespace and forwarding the types to various visitors to filter/import
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template<class Import, class StringType = boost::string_ref> | |
struct JsonVisitor | |
{ | |
JsonVisitor(Import& import,const boost::dynamic_bitset& filterresult):import(import),key(key),filterresult(filterresult){} | |
template<class Value> | |
bool operator()(const Value& v)const | |
{ | |
import.processKeyValue(current_key,v); | |
return true; | |
} | |
static_assert(detail::has_member_function_EndObject<Import,bool>::value, "Import requires a bool EndObject() method!"); | |
bool EndObject() | |
{ | |
if(filterresult.empty() || filterresult[index++]) | |
return import.EndObject(); | |
import.reset(); | |
return true; | |
} | |
bool Key(const char* key, size_t length, bool copy = false) | |
{ | |
current_key = boost::string_ref(key,lenght); | |
return true; | |
} | |
private: | |
boost::string_ref current_key; | |
Import& import; | |
const boost::dynamic_bitset& filterresult; | |
size_t index = 0; | |
}; | |
using string2vectormap = std::map<std::string,std::vector<std::string> >; | |
struct ImportFilter | |
{ | |
ImportFilter(const string2vectormap& filtermap):filtermap(filtermap){} | |
bool operator()(const boost::string_ref& key, const std::string& value) | |
{ | |
auto it = filtermap.find(pair.first); | |
if(it != filtermap.end())//filter is present | |
return std::find(it->second.begin(), it->second.end(),value) == it->second.end(); | |
return false; | |
} | |
//import format only has strings, so no conversion is needed | |
template<class Value> | |
bool operator()(const std::string& key, const Value& ) | |
{ | |
return false; | |
} | |
private: | |
const string2vectormap& filtermap; | |
}; | |
template<class T, class InsertT> | |
struct JsonTableImport | |
{ | |
template<typename> | |
friend class JsonVisitor; | |
using ImportJsonVisitor = JsonVisitor<JsonTableImport>; | |
using stringmap = std::map<std::string,std::string>; | |
JsonTableImport(const stringmap& fieldmapping,const string2vectormap& filtermapping,InsertT& insert,const T& current_item = T()):insert(insert),current_item(current_item){} | |
// LoadJson json AS JSONVALUE/JSONDOCUMENT f(const std::string&) - loads json from string | |
// AcceptJsonVisitor void/bool f(json, VISITOR) - applys visitor to json | |
template<class LoadJson, class AcceptJsonVisitor> | |
void import(const std::string& data,const LoadJson& loadjson, const AcceptJsonVisitor& accept) | |
{ | |
auto jsondoc = loadjson(data); | |
boost::dynamic_bitset filterresult; | |
if(!filtermapping.empty()) | |
{ | |
ImportFilter filtercallback(filtermapping); | |
json::JsonFilterVisitor<ImportFilter> filtervisitor(filtercallback,filterresult); | |
accept(jsondoc,filtervisitor); | |
} | |
//filter has created the filter result. | |
ImportJsonVisitor json_visitor(*this,filterresult); | |
json::JsonHandler<ImportJsonVisitor> json_import_handler(json_visitor); | |
access.setAccess(current_item); | |
accept(jsondoc,json_import_handler); | |
} | |
private: | |
template<class V> | |
void processKeyValue(const std::string& key, V& value) | |
{ | |
auto it = fieldmapping.find(key); | |
if( it != fieldmapping.end())return;//field set for import. | |
access.writeValue2Field(it->second,value); | |
} | |
template<class V> | |
void processKeyValue(const boost::string_ref& key, V& value) | |
{ | |
auto it = fieldmapping.find(key.to_string()); | |
if( it != fieldmapping.end())return;//field set for import. | |
access.writeValue2Field(it->second,value); | |
} | |
void EndObject() | |
{ | |
insert(current_item); | |
current_item = T(); | |
} | |
void reset() | |
{ | |
current_item = T(); | |
} | |
stringmap fieldmapping; | |
string2vectormap filtermapping; | |
InsertT insert; | |
StructAccess<T> access; | |
T current_item; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment