update json parsing to be more flexible and report better errors
This commit is contained in:
parent
38f97ef61a
commit
68e50ee166
2 changed files with 113 additions and 93 deletions
|
|
@ -8,6 +8,7 @@
|
|||
#include <fc/tuple.hpp>
|
||||
#include <fc/vector.hpp>
|
||||
#include <fc/typename.hpp>
|
||||
#include <fc/error_report.hpp>
|
||||
|
||||
//#include <typeinfo>
|
||||
|
||||
|
|
@ -19,21 +20,24 @@ namespace fc {
|
|||
struct cast_visitor : value::const_visitor {
|
||||
cast_visitor( T& out )
|
||||
:m_out(out){}
|
||||
virtual void operator()( const int8_t& v ){ m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const int16_t& v ){ m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const int32_t& v ){ m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const int64_t& v ){ m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const uint8_t& v ){ m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const uint16_t& v ){ m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const uint32_t& v ){ m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const uint64_t& v ){ m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const float& v ){ m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const double& v ){ m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const bool& v ){ m_out = v; }
|
||||
virtual void operator()( const fc::string& v ) { m_out = fc::lexical_cast<T>(v); }
|
||||
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( const int8_t& v ) { m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const int16_t& v ) { m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const int32_t& v ) { m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const int64_t& v ) { m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const uint8_t& v ) { m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const uint16_t& v ) { m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const uint32_t& v ) { m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const uint64_t& v ) { m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const float& v ) { m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const double& v ) { m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const bool& v ) { m_out = v; }
|
||||
virtual void operator()( const fc::string& v ) { m_out = fc::lexical_cast<T>(v); }
|
||||
virtual void operator()( const value::object& ) { FC_THROW_REPORT("bad cast to ${type} from object",
|
||||
fc::value().set("type",fc::get_typename<T>::name())); }
|
||||
virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast to ${type} from array",
|
||||
fc::value().set("type",fc::get_typename<T>::name())); }
|
||||
virtual void operator()( ) { FC_THROW_REPORT("bad cast to ${type} from null",
|
||||
fc::value().set("type",fc::get_typename<T>::name())); }
|
||||
private:
|
||||
T& m_out;
|
||||
};
|
||||
|
|
@ -53,9 +57,9 @@ namespace fc {
|
|||
virtual void operator()( const double& v ){ m_out = v != 0; }
|
||||
virtual void operator()( const bool& v ){ m_out = v; }
|
||||
virtual void operator()( const fc::string& v ) { m_out = !(v != "true"); }
|
||||
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( const value::object& ) { FC_THROW_REPORT("bad cast to bool from object"); }
|
||||
virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast to bool from array"); }
|
||||
virtual void operator()( ) { FC_THROW_REPORT("bad cast to bool from null"); }
|
||||
private:
|
||||
bool& m_out;
|
||||
};
|
||||
|
|
@ -64,21 +68,21 @@ namespace fc {
|
|||
struct cast_visitor<fc::string> : value::const_visitor {
|
||||
cast_visitor( fc::string& out )
|
||||
:m_out(out){}
|
||||
virtual void operator()( const int8_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const int16_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const int32_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const int64_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const uint8_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const uint16_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const uint32_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const uint64_t& v ){ m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const float& v ){ m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const double& v ){ m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const bool& v ){ m_out = v != 0 ? "true" : "false"; }
|
||||
virtual void operator()( const fc::string& v ) { m_out = v; }
|
||||
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( const int8_t& v ) { m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const int16_t& v ) { m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const int32_t& v ) { m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const int64_t& v ) { m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const uint8_t& v ) { m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const uint16_t& v ) { m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const uint32_t& v ) { m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const uint64_t& v ) { m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const float& v ) { m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const double& v ) { m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const bool& v ) { m_out = v != 0 ? "true" : "false"; }
|
||||
virtual void operator()( const fc::string& v ) { m_out = v; }
|
||||
virtual void operator()( const value::object& ){ FC_THROW_REPORT("bad cast to string from object"); }
|
||||
virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast to string from array"); }
|
||||
virtual void operator()( ) { m_out = fc::string(); }
|
||||
|
||||
private:
|
||||
fc::string& m_out;
|
||||
|
|
@ -88,21 +92,21 @@ namespace fc {
|
|||
struct cast_visitor<value::array> : value::const_visitor {
|
||||
cast_visitor( value::array& out )
|
||||
:m_out(out){}
|
||||
virtual void operator()( const int8_t& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const int16_t& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const int32_t& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const int64_t& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const uint8_t& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const uint16_t& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const uint32_t& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const uint64_t& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const float& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const double& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const bool& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const fc::string& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const value::array& a ) { m_out = a; }
|
||||
virtual void operator()( ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const int8_t& v ) { FC_THROW_REPORT("bad cast to array from int8");}
|
||||
virtual void operator()( const int16_t& v ) { FC_THROW_REPORT("bad cast to array from int16");}
|
||||
virtual void operator()( const int32_t& v ) { FC_THROW_REPORT("bad cast to array from int32");}
|
||||
virtual void operator()( const int64_t& v ) { FC_THROW_REPORT("bad cast to array from int32");}
|
||||
virtual void operator()( const uint8_t& v ) { FC_THROW_REPORT("bad cast to array from uint8");}
|
||||
virtual void operator()( const uint16_t& v ) { FC_THROW_REPORT("bad cast to array from uint16");}
|
||||
virtual void operator()( const uint32_t& v ) { FC_THROW_REPORT("bad cast to array from uint32");}
|
||||
virtual void operator()( const uint64_t& v ) { FC_THROW_REPORT("bad cast to array from uint64");}
|
||||
virtual void operator()( const float& v ) { FC_THROW_REPORT("bad cast to array from float");}
|
||||
virtual void operator()( const double& v ) { FC_THROW_REPORT("bad cast to array from double");}
|
||||
virtual void operator()( const bool& v ) { FC_THROW_REPORT("bad cast to array from bool");}
|
||||
virtual void operator()( const fc::string& v ) { FC_THROW_REPORT("bad cast to array from string");}
|
||||
virtual void operator()( const value::object& ) { FC_THROW_REPORT("bad cast to array from object");}
|
||||
virtual void operator()( const value::array& a ) { m_out = a; }
|
||||
virtual void operator()( ) { m_out = value::array(); }
|
||||
|
||||
private:
|
||||
value::array& m_out;
|
||||
|
|
@ -112,21 +116,21 @@ namespace fc {
|
|||
struct cast_visitor<value::object> : value::const_visitor {
|
||||
cast_visitor( value::object& out )
|
||||
:m_out(out){}
|
||||
virtual void operator()( const int8_t& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const int16_t& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const int32_t& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const int64_t& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const uint8_t& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const uint16_t& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const uint32_t& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const uint64_t& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const float& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const double& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const bool& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const fc::string& v ){ FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const value::object& a ) { m_out = a; }
|
||||
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const int8_t& v ){ FC_THROW_REPORT("bad cast to array from int8");}
|
||||
virtual void operator()( const int16_t& v ){ FC_THROW_REPORT("bad cast to array from int16");}
|
||||
virtual void operator()( const int32_t& v ){ FC_THROW_REPORT("bad cast to array from int32");}
|
||||
virtual void operator()( const int64_t& v ){ FC_THROW_REPORT("bad cast to array from int32");}
|
||||
virtual void operator()( const uint8_t& v ){ FC_THROW_REPORT("bad cast to array from uint8");}
|
||||
virtual void operator()( const uint16_t& v ){ FC_THROW_REPORT("bad cast to array from uint16");}
|
||||
virtual void operator()( const uint32_t& v ){ FC_THROW_REPORT("bad cast to array from uint32");}
|
||||
virtual void operator()( const uint64_t& v ){ FC_THROW_REPORT("bad cast to array from uint64");}
|
||||
virtual void operator()( const float& v ){ FC_THROW_REPORT("bad cast to array from float");}
|
||||
virtual void operator()( const double& v ){ FC_THROW_REPORT("bad cast to array from double");}
|
||||
virtual void operator()( const bool& v ){ FC_THROW_REPORT("bad cast to array from bool");}
|
||||
virtual void operator()( const fc::string& v ) { FC_THROW_REPORT("bad cast to array from string");}
|
||||
virtual void operator()( const value::object& a ) { m_out = a; }
|
||||
virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast");}
|
||||
virtual void operator()( ) { m_out = value::object(); }
|
||||
|
||||
private:
|
||||
value::object& m_out;
|
||||
|
|
@ -158,28 +162,35 @@ namespace fc {
|
|||
struct cast_visitor<fc::vector<T>> : value::const_visitor {
|
||||
cast_visitor( fc::vector<T>& out )
|
||||
:m_out(out){}
|
||||
virtual void operator()( const int8_t& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const int16_t& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const int32_t& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const int64_t& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const uint8_t& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const uint16_t& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const uint32_t& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const uint64_t& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const float& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const double& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const bool& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const fc::string& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const value::object& a ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const int8_t& v ) { FC_THROW_REPORT("bad cast to vector<T> from int8");}
|
||||
virtual void operator()( const int16_t& v ) { FC_THROW_REPORT("bad cast to vector<T> from int16");}
|
||||
virtual void operator()( const int32_t& v ) { FC_THROW_REPORT("bad cast to vector<T> from int32");}
|
||||
virtual void operator()( const int64_t& v ) { FC_THROW_REPORT("bad cast to vector<T> from int64");}
|
||||
virtual void operator()( const uint8_t& v ) { FC_THROW_REPORT("bad cast to vector<T> from uint8");}
|
||||
virtual void operator()( const uint16_t& v ) { FC_THROW_REPORT("bad cast to vector<T> from uint16");}
|
||||
virtual void operator()( const uint32_t& v ) { FC_THROW_REPORT("bad cast to vector<T> from uint32");}
|
||||
virtual void operator()( const uint64_t& v ) { FC_THROW_REPORT("bad cast to vector<T> from uint64");}
|
||||
virtual void operator()( const float& v ) { FC_THROW_REPORT("bad cast to vector<T> from float");}
|
||||
virtual void operator()( const double& v ) { FC_THROW_REPORT("bad cast to vector<T> from double");}
|
||||
virtual void operator()( const bool& v ) { FC_THROW_REPORT("bad cast to vector<T> from bool");}
|
||||
virtual void operator()( const fc::string& v ) { FC_THROW_REPORT("bad cast to vector<T> from string");}
|
||||
virtual void operator()( const value::object& a ) { FC_THROW_REPORT("bad cast to vector<T> from object");}
|
||||
virtual void operator()( const value::array& a ) {
|
||||
m_out.resize(0);
|
||||
m_out.reserve( a.fields.size() );
|
||||
int idx = 0;
|
||||
for( auto i = a.fields.begin(); i != a.fields.end(); ++i ) {
|
||||
m_out.push_back( value_cast<T>( *i ) );
|
||||
try {
|
||||
m_out.push_back( value_cast<T>( *i ) );
|
||||
} catch( fc::error_report& er ) {
|
||||
throw FC_REPORT_PUSH( er, "Error parsing array index ${index} to ${type}",
|
||||
fc::value().set("index", idx).set("type",fc::get_typename<T>::name()) );
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void operator()( ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( ) { FC_THROW_REPORT("bad cast");}
|
||||
|
||||
private:
|
||||
fc::vector<T>& m_out;
|
||||
|
|
@ -189,20 +200,20 @@ namespace fc {
|
|||
|
||||
template<>
|
||||
struct cast_visitor<void> : value::const_visitor {
|
||||
virtual void operator()( const int8_t& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const int16_t& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const int32_t& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const int64_t& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const uint8_t& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const uint16_t& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const uint32_t& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const uint64_t& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const float& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const double& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const bool& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const fc::string& v ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const value::object& a ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( const int8_t& v ) { FC_THROW_REPORT("bad cast");}
|
||||
virtual void operator()( const int16_t& v ) { FC_THROW_REPORT("bad cast");}
|
||||
virtual void operator()( const int32_t& v ) { FC_THROW_REPORT("bad cast");}
|
||||
virtual void operator()( const int64_t& v ) { FC_THROW_REPORT("bad cast");}
|
||||
virtual void operator()( const uint8_t& v ) { FC_THROW_REPORT("bad cast");}
|
||||
virtual void operator()( const uint16_t& v ) { FC_THROW_REPORT("bad cast");}
|
||||
virtual void operator()( const uint32_t& v ) { FC_THROW_REPORT("bad cast");}
|
||||
virtual void operator()( const uint64_t& v ) { FC_THROW_REPORT("bad cast");}
|
||||
virtual void operator()( const float& v ) { FC_THROW_REPORT("bad cast");}
|
||||
virtual void operator()( const double& v ) { FC_THROW_REPORT("bad cast");}
|
||||
virtual void operator()( const bool& v ) { FC_THROW_REPORT("bad cast");}
|
||||
virtual void operator()( const fc::string& v ) { FC_THROW_REPORT("bad cast");}
|
||||
virtual void operator()( const value::object& a ) { FC_THROW_REPORT("bad cast");}
|
||||
virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast");}
|
||||
virtual void operator()( ) { }
|
||||
};
|
||||
template<typename IsTuple=fc::false_type>
|
||||
|
|
@ -221,7 +232,11 @@ namespace fc {
|
|||
:_val(v),idx(0){}
|
||||
template<typename Member>
|
||||
void operator()( Member& m ) {
|
||||
m = value_cast<Member>(_val[idx]);
|
||||
try {
|
||||
m = value_cast<Member>(_val[idx]);
|
||||
} catch ( fc::error_report& er ) {
|
||||
throw FC_REPORT_PUSH( er, "Error parsing tuple element ${index}", fc::value().set("index",idx) );
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
const value& _val;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <fc/value.hpp>
|
||||
#include <fc/value_cast.hpp>
|
||||
#include <fc/tuple.hpp>
|
||||
#include <fc/error_report.hpp>
|
||||
|
||||
namespace fc {
|
||||
template<typename T>
|
||||
|
|
@ -129,7 +130,11 @@ namespace fc {
|
|||
template<typename T, typename C, T (C::*p)>
|
||||
void operator()( const char* name )const {
|
||||
if( obj.find(name) != obj.end()) {
|
||||
try {
|
||||
fc::unpack( obj[name], c.*p );
|
||||
} catch ( fc::error_report& er ) {
|
||||
throw FC_REPORT_PUSH( er, "Error parsing field '${field_name}'", fc::value().set("field_name",name) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( !is_optional< typename fc::remove_reference<decltype(c.*p)>::type >::type::value ) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue