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