Joshua Moerman
12 years ago
4 changed files with 207 additions and 52 deletions
@ -0,0 +1,123 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <utility> |
||||
|
#include <type_traits> |
||||
|
#include <stdexcept> |
||||
|
|
||||
|
#include <boost/fusion/include/define_struct.hpp> |
||||
|
#include <boost/fusion/include/for_each.hpp> |
||||
|
#include <boost/fusion/include/at.hpp> |
||||
|
|
||||
|
#include <json_spirit/json_spirit.h> |
||||
|
|
||||
|
namespace js = json_spirit; |
||||
|
|
||||
|
inline js::Value parse_json(std::string const & in){ |
||||
|
js::Value value; |
||||
|
js::read(in, value); |
||||
|
return value; |
||||
|
} |
||||
|
|
||||
|
inline std::string write_json(js::Value const & v){ |
||||
|
return js::write(v); |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
*** WRITING *** |
||||
|
Note: Does not yet support arrays, only basic types, std::strings and user defined types (with boost::fusion adaption) |
||||
|
*/ |
||||
|
|
||||
|
// Basic types
|
||||
|
template <typename T> |
||||
|
typename std::enable_if<!std::is_class<T>::value && !std::is_pointer<T>::value, js::Value>::type to_json(T const & x){ |
||||
|
return x; |
||||
|
} |
||||
|
|
||||
|
inline js::Value to_json(std::string const & x){ |
||||
|
return x; |
||||
|
} |
||||
|
|
||||
|
// Compound types (need recursion)
|
||||
|
template <typename T> |
||||
|
typename std::enable_if<std::is_class<T>::value, js::Value>::type to_json(T const & x); |
||||
|
|
||||
|
// boost::fusion magics
|
||||
|
template<typename T, typename N> |
||||
|
struct write_itr{ |
||||
|
typedef typename boost::mpl::next<N>::type next_t; |
||||
|
typedef boost::fusion::extension::struct_member_name<T, N::value> name_t; |
||||
|
|
||||
|
static inline void exec(js::Object & obj, const T& x){ |
||||
|
obj[name_t::call()] = to_json(boost::fusion::at<N>(x)); |
||||
|
write_itr<T, next_t>::exec(obj, x); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct write_itr<T, typename boost::fusion::result_of::size<T>::type>{ |
||||
|
static inline void exec(js::Object & obj, const T& x) {} |
||||
|
}; |
||||
|
|
||||
|
// Compound types (need recursion)
|
||||
|
template <typename T> |
||||
|
typename std::enable_if<std::is_class<T>::value, js::Value>::type to_json(T const & x){ |
||||
|
js::Object obj; |
||||
|
write_itr<T, boost::mpl::int_<0>>::exec(obj, x); |
||||
|
return obj; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/*
|
||||
|
*** READING *** |
||||
|
Note: Does not yet support arrays, only basic types, std::strings and user defined types (with boost::fusion adaption) |
||||
|
*/ |
||||
|
|
||||
|
// Basic types
|
||||
|
template <typename T> |
||||
|
typename std::enable_if<std::is_integral<T>::value, T>::type from_json(js::Value const & x){ |
||||
|
return x.getInt64(); |
||||
|
} |
||||
|
|
||||
|
template <typename T> |
||||
|
typename std::enable_if<std::is_floating_point<T>::value, T>::type from_json(js::Value const & x){ |
||||
|
return x.getReal(); |
||||
|
} |
||||
|
|
||||
|
template <typename T> |
||||
|
typename std::enable_if<std::is_same<T, std::string>::value, T>::type from_json(js::Value const & x){ |
||||
|
return x.getString(); |
||||
|
} |
||||
|
|
||||
|
// Compound types (need recursion)
|
||||
|
template <typename T> |
||||
|
typename std::enable_if<std::is_class<T>::value && !std::is_same<T, std::string>::value, T>::type from_json(js::Value const & x); |
||||
|
|
||||
|
// boost::fusion magics
|
||||
|
template<typename T, typename N> |
||||
|
struct read_itr{ |
||||
|
typedef typename boost::fusion::result_of::value_at<T, N>::type current_t; |
||||
|
typedef typename boost::mpl::next<N>::type next_t; |
||||
|
typedef boost::fusion::extension::struct_member_name<T, N::value> name_t; |
||||
|
|
||||
|
static inline void exec(js::Object const & obj, T& x){ |
||||
|
try{ |
||||
|
boost::fusion::at<N>(x) = from_json<current_t>(obj.at(name_t::call())); |
||||
|
} catch(std::out_of_range& e) { |
||||
|
throw std::out_of_range(e.what() + std::string(": ") + name_t::call()); |
||||
|
} |
||||
|
read_itr<T, next_t>::exec(obj, x); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct read_itr<T, typename boost::fusion::result_of::size<T>::type>{ |
||||
|
static inline void exec(js::Object const & obj, T& x) {} |
||||
|
}; |
||||
|
|
||||
|
// Compound types (need recursion)
|
||||
|
template <typename T> |
||||
|
typename std::enable_if<std::is_class<T>::value && !std::is_same<T, std::string>::value, T>::type from_json(js::Value const & x){ |
||||
|
T ret; |
||||
|
read_itr<T, boost::mpl::int_<0>>::exec(x.getObject(), ret); |
||||
|
return ret; |
||||
|
} |
Reference in new issue