json.h
//
// Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
//
// See accompanying file COPYING.TXT file for licensing details.
//
#ifndef CPPCMS_JSON_H
#define CPPCMS_JSON_H
#include <cppcms/defs.h>
#include <cppcms/string_key.h>
#include <booster/copy_ptr.h>
#include <booster/backtrace.h>
#include <vector>
#include <map>
#include <string>
#include <iostream>
#include <limits>
namespace cppcms {
namespace json {
class value;
struct null {};
struct undefined {};
inline bool operator==(undefined const &/*l*/,undefined const &/*r*/) {return true;}
inline bool operator!=(undefined const &/*l*/,undefined const &/*r*/) {return false;}
inline bool operator==(null const &/*l*/,null const &/*r*/) {return true;}
inline bool operator!=(null const &/*l*/,null const &/*r*/) {return false;}
typedef std::vector<value> array;
typedef std::map<string_key,value> object;
#ifdef CPPCMS_DOXYGEN_DOCS
template<typename T>
struct traits {
static T get(value const &v);
static void set(value &v,T const &in);
};
#else
template<typename T>
struct traits;
#endif
typedef enum {
is_undefined,
is_null,
is_boolean,
is_number,
is_string,
is_object,
is_array
} json_type;
enum {
compact = 0,
readable = 1
};
class CPPCMS_API bad_value_cast : public booster::bad_cast {
public:
bad_value_cast();
bad_value_cast(std::string const &s);
bad_value_cast(std::string const &s,json_type actual);
bad_value_cast(std::string const &s,json_type expected, json_type actual);
virtual ~bad_value_cast() throw();
virtual const char* what() const throw();
private:
std::string msg_;
};
class value;
std::istream CPPCMS_API &operator>>(std::istream &in,value &v);
std::ostream CPPCMS_API &operator<<(std::ostream &out,value const &v);
std::ostream CPPCMS_API &operator<<(std::ostream &out,json_type);
class CPPCMS_API value {
public:
json_type type() const;
bool is_undefined() const;
bool is_null() const;
bool const &boolean() const;
double const &number() const;
std::string const &str() const;
json::object const &object() const;
json::array const &array() const;
bool &boolean();
double &number();
std::string &str();
json::object &object();
json::array &array();
void undefined();
void null();
void boolean(bool);
void number(double );
void str(std::string const &);
void object(json::object const &);
void array(json::array const &);
template<typename T>
T get_value() const
{
return traits<T>::get(*this);
}
template<typename T>
void set_value(T const &v)
{
traits<T>::set(*this,v);
}
value const &find(std::string const &path) const;
value const &find(char const *path) const;
value const &at(std::string const &path) const;
value const &at(char const *path) const;
value &at(std::string const &path);
value &at(char const *path);
void at(std::string const &path,value const &v);
void at(char const *path,value const &v);
template<typename T>
value(T const &v)
{
set_value(v);
}
json_type type(std::string const &path) const
{
return find(path).type();
}
json_type type(char const *path) const
{
return find(path).type();
}
template<typename T>
void set(std::string const &path,T const &v)
{
at(path,value(v));
}
template<typename T>
void set(char const *path,T const &v)
{
at(path,value(v));
}
std::string get(std::string const &path,char const *def) const
{
value const &v=find(path);
if(v.is_undefined())
return def;
try {
return v.get_value<std::string>();
}
catch(std::bad_cast const &e) {
return def;
}
}
std::string get(char const *path,char const *def) const
{
value const &v=find(path);
if(v.is_undefined())
return def;
try {
return v.get_value<std::string>();
}
catch(std::bad_cast const &e) {
return def;
}
}
template<typename T>
T get(std::string const &path) const
{
return at(path).get_value<T>();
}
template<typename T>
T get(char const *path) const
{
return at(path).get_value<T>();
}
template<typename T>
T get(char const *path,T const &def) const
{
value const &v=find(path);
if(v.is_undefined())
return def;
try {
return v.get_value<T>();
}
catch(std::bad_cast const &e) {
return def;
}
}
template<typename T>
T get(std::string const &path,T const &def) const
{
value const &v=find(path);
if(v.is_undefined())
return def;
try {
return v.get_value<T>();
}
catch(std::bad_cast const &e) {
return def;
}
}
value &operator[](std::string const &name);
value const &operator[](std::string const &name) const;
value &operator[](size_t n);
value const &operator[](size_t n) const;
std::string save(int how=compact) const;
void save(std::ostream &out,int how=compact) const;
bool load(std::istream &in,bool full,int *line_number=0);
bool operator==(value const &other) const;
bool operator!=(value const &other) const;
value(value const &other) :
d(other.d)
{
}
value const &operator=(value const &other)
{
d=other.d;
return *this;
}
value()
{
}
~value()
{
}
void swap(value &other)
{
d.swap(other.d);
}
private:
void write(std::ostream &out,int tabs) const;
void write_value(std::ostream &out,int tabs) const;
struct _data;
struct CPPCMS_API copyable {
_data *operator->() { return &*d; }
_data &operator*() { return *d; }
_data const *operator->() const { return &*d; }
_data const &operator*() const { return *d; }
copyable();
copyable(copyable const &r);
copyable const &operator=(copyable const &r);
~copyable();
void swap(copyable &other)
{
d.swap(other.d);
}
private:
booster::copy_ptr<_data> d;
} d;
friend struct copyable;
};
template<typename T1,typename T2>
struct traits<std::pair<T1,T2> > {
static std::pair<T1,T2> get(value const &v)
{
if(v.object().size()!=2)
throw bad_value_cast("Object with two members expected");
std::pair<T1,T2> pair(v.get_value<T1>("first"),v.get_value<T2>("second"));
return pair;
}
static void set(value &v,std::pair<T1,T2> const &in)
{
v=json::object();
v.set_value("first",in.first);
v.set_value("second",in.second);
}
};
template<typename T>
struct traits<std::vector<T> > {
static std::vector<T> get(value const &v)
{
std::vector<T> result;
json::array const &a=v.array();
result.resize(a.size());
for(unsigned i=0;i<a.size();i++)
result[i]=a[i].get_value<T>();
return result;
}
static void set(value &v,std::vector<T> const &in)
{
v=json::array();
json::array &a=v.array();
a.resize(in.size());
for(unsigned i=0;i<in.size();i++)
a[i].set_value(in[i]);
}
};
#define CPPCMS_JSON_SPECIALIZE(type,method) \
template<> \
struct traits<type> { \
static type get(value const &v) \
{ \
return v.method(); \
} \
static void set(value &v,type const &in)\
{ \
v.method(in); \
} \
};
CPPCMS_JSON_SPECIALIZE(bool,boolean);
CPPCMS_JSON_SPECIALIZE(double,number);
CPPCMS_JSON_SPECIALIZE(std::string,str);
CPPCMS_JSON_SPECIALIZE(json::object,object);
CPPCMS_JSON_SPECIALIZE(json::array,array);
#undef CPPCMS_JSON_SPECIALIZE
#define CPPCMS_JSON_SPECIALIZE_INT(type) \
template<> \
struct traits<type> { \
static type get(value const &v) \
{ \
type res=static_cast<type>(v.number()); \
if(res!=v.number()) \
throw bad_value_cast(); \
return res; \
} \
static void set(value &v,type const &in) \
{ \
if(std::numeric_limits<type>::digits > \
std::numeric_limits<double>::digits \
&& static_cast<double>(in)!=in) \
{ \
throw bad_value_cast(); \
} \
v.number(static_cast<double>(in)); \
} \
};
CPPCMS_JSON_SPECIALIZE_INT(char)
CPPCMS_JSON_SPECIALIZE_INT(unsigned char)
CPPCMS_JSON_SPECIALIZE_INT(signed char)
CPPCMS_JSON_SPECIALIZE_INT(wchar_t)
CPPCMS_JSON_SPECIALIZE_INT(short)
CPPCMS_JSON_SPECIALIZE_INT(unsigned short)
CPPCMS_JSON_SPECIALIZE_INT(int)
CPPCMS_JSON_SPECIALIZE_INT(unsigned int)
CPPCMS_JSON_SPECIALIZE_INT(long)
CPPCMS_JSON_SPECIALIZE_INT(unsigned long)
CPPCMS_JSON_SPECIALIZE_INT(long long)
CPPCMS_JSON_SPECIALIZE_INT(unsigned long long)
#undef CPPCMS_JSON_SPECIALIZE_INT
template<>
struct traits<float> {
static float get(value const &v)
{
double r=v.number();
if( r < std::numeric_limits<float>::min()
|| std::numeric_limits<float>::max() < r )
{
throw bad_value_cast();
}
return static_cast<float>(r);
}
static void set(value &v,float const &in)
{
v.number(in);
}
};
template<>
struct traits<long double> {
static long double get(value const &v)
{
return v.number();
}
static void set(value &v,long double const &in)
{
if( in < std::numeric_limits<double>::min()
|| std::numeric_limits<double>::max() < in )
{
throw bad_value_cast();
}
v.number(static_cast<double>(in));
}
};
template<>
struct traits<json::null> {
static void set(value &v,json::null const &/*in*/)
{
v.null();
}
};
template<int n>
struct traits<char[n]> {
typedef char vtype[n];
static void set(value &v,vtype const &in)
{
v.str(in);
}
};
template<int n>
struct traits<char const [n]> {
typedef char const vtype[n];
static void set(value &v,vtype const &in)
{
v.str(in);
}
};
template<>
struct traits<char const *> {
static void set(value &v,char const * const &in)
{
v.str(in);
}
};
} // json
} // cppcms
#endif
cppcms::json::traits::get
static T get(value const &v)
cppcms::json::value
This class is central representation of json objects.
Definition: json.h:142
cppcms::json::json_type
json_type
Definition: json.h:84
cppcms::json::compact
Print JSON values in most compact format.
Definition: json.h:96
cppcms::json::value::set
void set(char const *path, T const &v)
Definition: json.h:350
cppcms::json::value::value
value(value const &other)
Definition: json.h:502
cppcms::json::value::type
json_type type(std::string const &path) const
Definition: json.h:324
cppcms::json::undefined
Special object that is convertible to undefined json value.
Definition: json.h:39
cppcms::json::is_boolean
boolean value
Definition: json.h:87
cppcms::json::is_string
string value
Definition: json.h:89
cppcms::json::object
std::map< string_key, value > object
The json::object - std::map of json::value's.
Definition: json.h:53
booster::copy_ptr< _data >
cppcms::json::null
Special object that is convertible to null json value.
Definition: json.h:35
cppcms::json::value::get_value
T get_value() const
Definition: json.h:236
cppcms::json::value::set_value
void set_value(T const &v)
Definition: json.h:245
booster::locale::period::operator*
date_time_period operator*(period::period_type f, T v)
Definition: date_time.h:335
cppcms::json::value::value
value(T const &v)
Definition: json.h:314
cppcms::json::is_object
object value
Definition: json.h:90
cppcms::json::value::operator=
value const & operator=(value const &other)
Definition: json.h:509
cppcms::json::bad_value_cast
The error that is thrown in case of bad conversion of json::value to ordinary value.
Definition: json.h:106
cppcms::json::value::swap
void swap(value &other)
Definition: json.h:532
cppcms::json::value::is_undefined
bool is_undefined() const
cppcms::json::operator<<
std::ostream CPPCMS_API & operator<<(std::ostream &out, value const &v)
cppcms::json::operator>>
std::istream CPPCMS_API & operator>>(std::istream &in, value &v)
cppcms::json::is_null
null value
Definition: json.h:86
booster::locale::as::number
std::ios_base & number(std::ios_base &ios)
Definition: formatting.h:292
cppcms::json::traits::set
static void set(value &v, T const &in)
booster::bad_cast
Same as std::bad_cast but records stack trace.
Definition: backtrace.h:151
cppcms::json::value::type
json_type type(char const *path) const
Definition: json.h:333
cppcms::json::traits
The type traits schema for converting json values to/from orinary objects i.e. serialization from JSO...
Definition: json.h:62
cppcms::json::is_number
numeric value
Definition: json.h:88
cppcms::json::value::~value
~value()
Definition: json.h:525
cppcms::json::array
std::vector< value > array
The json::array - std::vector of json::value's.
Definition: json.h:49
cppcms::json::is_undefined
Undefined value.
Definition: json.h:85
cppcms::json::is_array
array value
Definition: json.h:91
cppcms::json::readable
Print JSON values in human readable format (with identention)
Definition: json.h:97
cppcms::json::value::set
void set(std::string const &path, T const &v)
Definition: json.h:342
cppcms::json::value::value
value()
Definition: json.h:517