Вы не перечислили типы таких вещей, как bar
, поэтому я просто использую Bar
для этого типа.
Вы можете использовать несколько вспомогательных методов, используя коды состоянияили исключения, в зависимости от того, насколько часто вы ожидаете сбои.
bool get_string(std::string& result, const Bar& bar, const char* name)
{
if(bar.isMember(name) && bar[name].isString())
{
result = bar[name].asString();
return true;
}
return false;
}
// and similarly
bool get_int(int& result, const Bar& bar, const char* name)
{
if(bar.isMember(name) && bar[name].isInt())
{
result = bar[name].asInt();
return true;
}
return false;
}
Затем вы можете использовать его с:
JSON::Value bar;
std::string baz;
int buzz;
if(get_object(bar, root, "bar"))
{
if (get_string(baz, bar, "baz")
&& get_int(buzz, bar, "buzz"))
{
// do things with baz and buzz
}
else{ err["bar"] = argument_error; }
}
Что немного чище, но не на дрожжахЕсли вы ожидаете присутствия того, что ищете, и сбои маловероятны, мы можем использовать исключения.И мы также можем использовать шаблоны:
// set up template forms to check types
template<typename T> bool is_a(const Bar& b);
template<> bool is_a<std::string>(const Bar& b) { return b.isString(); }
template<> bool is_a<int> (const Bar& b) { return b.isInt(); }
template<> bool is_a<JSON::Value>(const Bar& b) { return b.isObject(); }
// templates to extract as a type
template<typename T> T as_type(const Bar& b);
template<> std::string as_type<std::string>(const Bar& b) { return b.asString(); }
template<> int as_type<int> (const Bar& b) { return b.asInt(); }
template<> JSON::Value as_type<JSON::Value>(const Bar& b) { return b.asObject(); }
// the one extraction method
template<typename T>
T get(const Bar& bar, const char* name)
{
if ( ! bar.isMember(name)) throw std::runtime_error("not a member");
if ( ! is_a<T>(bar[name])) throw std::runtime_error("wrong type");
return as_type<T>(bar[name]);
}
// and now we use it
try
{
JSON::Value bar = get<JSON::Value>(root, "bar");
std::string baz = get<std::string>(bar, "baz");
int buzz = get<int>(bar, "buzz");
// do things with baz and buzz
}
catch (const std::runtime_error& exc)
{
err["bar"] = argument_error;
}
Для установки требуется больше методов, но теперь ее использование очень просто и чисто.