update json parsing to be more flexible and report better errors

This commit is contained in:
Daniel Larimer 2013-01-11 14:13:47 -05:00
parent 38f97ef61a
commit 68e50ee166
2 changed files with 113 additions and 93 deletions

View file

@ -8,6 +8,7 @@
#include <fc/tuple.hpp> #include <fc/tuple.hpp>
#include <fc/vector.hpp> #include <fc/vector.hpp>
#include <fc/typename.hpp> #include <fc/typename.hpp>
#include <fc/error_report.hpp>
//#include <typeinfo> //#include <typeinfo>
@ -19,21 +20,24 @@ namespace fc {
struct cast_visitor : value::const_visitor { struct cast_visitor : value::const_visitor {
cast_visitor( T& out ) cast_visitor( T& out )
:m_out(out){} :m_out(out){}
virtual void operator()( const int8_t& v ){ m_out = fc::numeric_cast<T>(v); } 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 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 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 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 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 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 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 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 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 double& v ) { m_out = fc::numeric_cast<T>(v); }
virtual void operator()( const bool& v ){ m_out = 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 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::object& ) { FC_THROW_REPORT("bad cast to ${type} from object",
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); } fc::value().set("type",fc::get_typename<T>::name())); }
virtual void operator()( ) { FC_THROW_MSG("bad cast"); } 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: private:
T& m_out; T& m_out;
}; };
@ -53,9 +57,9 @@ namespace fc {
virtual void operator()( const double& v ){ m_out = v != 0; } virtual void operator()( const double& v ){ m_out = v != 0; }
virtual void operator()( const bool& v ){ m_out = v; } virtual void operator()( const bool& v ){ m_out = v; }
virtual void operator()( const fc::string& v ) { m_out = !(v != "true"); } 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::object& ) { FC_THROW_REPORT("bad cast to bool from object"); }
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); } virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast to bool from array"); }
virtual void operator()( ) { FC_THROW_MSG("bad cast"); } virtual void operator()( ) { FC_THROW_REPORT("bad cast to bool from null"); }
private: private:
bool& m_out; bool& m_out;
}; };
@ -64,21 +68,21 @@ namespace fc {
struct cast_visitor<fc::string> : value::const_visitor { struct cast_visitor<fc::string> : value::const_visitor {
cast_visitor( fc::string& out ) cast_visitor( fc::string& out )
:m_out(out){} :m_out(out){}
virtual void operator()( const int8_t& v ){ m_out = fc::lexical_cast<fc::string>(v); } 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 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 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 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 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 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 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 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 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 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 bool& v ) { m_out = v != 0 ? "true" : "false"; }
virtual void operator()( const fc::string& v ) { m_out = v; } 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::object& ){ FC_THROW_REPORT("bad cast to string from object"); }
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); } virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast to string from array"); }
virtual void operator()( ) { FC_THROW_MSG("bad cast"); } virtual void operator()( ) { m_out = fc::string(); }
private: private:
fc::string& m_out; fc::string& m_out;
@ -88,21 +92,21 @@ namespace fc {
struct cast_visitor<value::array> : value::const_visitor { struct cast_visitor<value::array> : value::const_visitor {
cast_visitor( value::array& out ) cast_visitor( value::array& out )
:m_out(out){} :m_out(out){}
virtual void operator()( const int8_t& v ){ 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_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} virtual void operator()( const uint64_t& v ) { FC_THROW_REPORT("bad cast to array from uint64");}
virtual void operator()( const float& v ){ FC_THROW_MSG("bad cast");} virtual void operator()( const float& v ) { FC_THROW_REPORT("bad cast to array from float");}
virtual void operator()( const double& v ){ FC_THROW_MSG("bad cast");} virtual void operator()( const double& v ) { FC_THROW_REPORT("bad cast to array from double");}
virtual void operator()( const bool& v ){ FC_THROW_MSG("bad cast");} virtual void operator()( const bool& v ) { FC_THROW_REPORT("bad cast to array from bool");}
virtual void operator()( const fc::string& v ){ FC_THROW_MSG("bad cast");} virtual void operator()( const fc::string& v ) { FC_THROW_REPORT("bad cast to array from string");}
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast");} 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()( const value::array& a ) { m_out = a; }
virtual void operator()( ) { FC_THROW_MSG("bad cast");} virtual void operator()( ) { m_out = value::array(); }
private: private:
value::array& m_out; value::array& m_out;
@ -112,21 +116,21 @@ namespace fc {
struct cast_visitor<value::object> : value::const_visitor { struct cast_visitor<value::object> : value::const_visitor {
cast_visitor( value::object& out ) cast_visitor( value::object& out )
:m_out(out){} :m_out(out){}
virtual void operator()( const int8_t& v ){ 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_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} virtual void operator()( const uint64_t& v ){ FC_THROW_REPORT("bad cast to array from uint64");}
virtual void operator()( const float& v ){ FC_THROW_MSG("bad cast");} virtual void operator()( const float& v ){ FC_THROW_REPORT("bad cast to array from float");}
virtual void operator()( const double& v ){ FC_THROW_MSG("bad cast");} virtual void operator()( const double& v ){ FC_THROW_REPORT("bad cast to array from double");}
virtual void operator()( const bool& v ){ FC_THROW_MSG("bad cast");} virtual void operator()( const bool& v ){ FC_THROW_REPORT("bad cast to array from bool");}
virtual void operator()( const fc::string& v ){ FC_THROW_MSG("bad cast");} 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::object& a ) { m_out = a; }
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast");} virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( ) { FC_THROW_MSG("bad cast");} virtual void operator()( ) { m_out = value::object(); }
private: private:
value::object& m_out; value::object& m_out;
@ -158,28 +162,35 @@ namespace fc {
struct cast_visitor<fc::vector<T>> : value::const_visitor { struct cast_visitor<fc::vector<T>> : value::const_visitor {
cast_visitor( fc::vector<T>& out ) cast_visitor( fc::vector<T>& out )
:m_out(out){} :m_out(out){}
virtual void operator()( const int8_t& v ) { 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_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} virtual void operator()( const float& v ) { FC_THROW_REPORT("bad cast to vector<T> from float");}
virtual void operator()( const double& v ) { FC_THROW_MSG("bad cast");} virtual void operator()( const double& v ) { FC_THROW_REPORT("bad cast to vector<T> from double");}
virtual void operator()( const bool& v ) { FC_THROW_MSG("bad cast");} 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_MSG("bad cast");} 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_MSG("bad cast");} virtual void operator()( const value::object& a ) { FC_THROW_REPORT("bad cast to vector<T> from object");}
virtual void operator()( const value::array& a ) { virtual void operator()( const value::array& a ) {
m_out.resize(0); m_out.resize(0);
m_out.reserve( a.fields.size() ); m_out.reserve( a.fields.size() );
int idx = 0;
for( auto i = a.fields.begin(); i != a.fields.end(); ++i ) { 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: private:
fc::vector<T>& m_out; fc::vector<T>& m_out;
@ -189,20 +200,20 @@ namespace fc {
template<> template<>
struct cast_visitor<void> : value::const_visitor { struct cast_visitor<void> : value::const_visitor {
virtual void operator()( const int8_t& v ) { 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_MSG("bad cast");} virtual void operator()( const int16_t& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const int32_t& v ) { FC_THROW_MSG("bad cast");} virtual void operator()( const int32_t& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const int64_t& v ) { FC_THROW_MSG("bad cast");} virtual void operator()( const int64_t& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const uint8_t& v ) { FC_THROW_MSG("bad cast");} virtual void operator()( const uint8_t& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const uint16_t& v ) { FC_THROW_MSG("bad cast");} virtual void operator()( const uint16_t& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const uint32_t& v ) { FC_THROW_MSG("bad cast");} virtual void operator()( const uint32_t& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const uint64_t& v ) { FC_THROW_MSG("bad cast");} virtual void operator()( const uint64_t& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const float& v ) { FC_THROW_MSG("bad cast");} virtual void operator()( const float& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const double& v ) { FC_THROW_MSG("bad cast");} virtual void operator()( const double& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const bool& v ) { FC_THROW_MSG("bad cast");} virtual void operator()( const bool& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const fc::string& v ) { FC_THROW_MSG("bad cast");} virtual void operator()( const fc::string& v ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const value::object& a ) { FC_THROW_MSG("bad cast");} virtual void operator()( const value::object& a ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast");} virtual void operator()( const value::array& ) { FC_THROW_REPORT("bad cast");}
virtual void operator()( ) { } virtual void operator()( ) { }
}; };
template<typename IsTuple=fc::false_type> template<typename IsTuple=fc::false_type>
@ -221,7 +232,11 @@ namespace fc {
:_val(v),idx(0){} :_val(v),idx(0){}
template<typename Member> template<typename Member>
void operator()( Member& m ) { 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; ++idx;
} }
const value& _val; const value& _val;

View file

@ -5,6 +5,7 @@
#include <fc/value.hpp> #include <fc/value.hpp>
#include <fc/value_cast.hpp> #include <fc/value_cast.hpp>
#include <fc/tuple.hpp> #include <fc/tuple.hpp>
#include <fc/error_report.hpp>
namespace fc { namespace fc {
template<typename T> template<typename T>
@ -129,7 +130,11 @@ namespace fc {
template<typename T, typename C, T (C::*p)> template<typename T, typename C, T (C::*p)>
void operator()( const char* name )const { void operator()( const char* name )const {
if( obj.find(name) != obj.end()) { if( obj.find(name) != obj.end()) {
try {
fc::unpack( obj[name], c.*p ); 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 { else {
if( !is_optional< typename fc::remove_reference<decltype(c.*p)>::type >::type::value ) { if( !is_optional< typename fc::remove_reference<decltype(c.*p)>::type >::type::value ) {