请参考我的相关文章。
假定有一个类response,两个字段,一个是status,0代表正确。其他代表错误。另一个是message字段,表示操作结果的具体信息。代码如下:
class response { public: //0 is ok //other values are wrong int status; string message; };
namespace cppcms { namespace json { template<> struct traits<response> { static void set(value &v, response const& in) { v.set("status", in.status); v.set("message", in.message); } }; } }
#include <cppcms/json.h> ... int main(int argc, char** argv) { response r1; r1.status=0; r1.message="ok"; cout<< cppcms::json::value(r1)<<endl; response r2; r2.status=1; r2.message="unknown error"; cout<< cppcms::json::value(r2)<<endl; return 0; }
之所以很容易就转换成JSON串,是因为使用了value类。现在来分析一下上面的调用代码里面是如何工作的。
1.cppcms::json::value(r1) 创建了匿名对象value,value的构造函数内部调用了set_value方法。参数v此时就是response对象。
template<typename T> value(T const &v) { set_value(v); }
template<typename T> void set_value(T const &v) { traits<T>::set(this,v); }
std::ostream &operator<<(std::ostream &out,value const &v) { v.save(out); return out; } void value::save(std::ostream &out,int how) const { int tabs=(how & readable) ? 0 : -1; write(out,tabs); } void value::write(std::ostream &out,int tabs) const { std::locale original(out.getloc()); out.imbue(std::locale("C")); try { write_value(out,tabs); } catch(...) { out.imbue(original); throw; } out.imbue(original); } void value::write_value(std::ostream &out,int tabs) const { switch(type()) { case json::is_undefined: throw bad_value_cast("Can't write undefined value to stream"); case json::is_null: out<<"null"; break; case json::is_number: out<<std::setprecision(std::numeric_limits<double>::digits10+1)<<number(); break; case json::is_string: out<<escape(str()); break; case json::is_boolean: out<< (boolean() ? "true" : "false") ; break; case json::is_array: { json::array const &a=array(); unsigned i; indent(out,'[',tabs); for(i=0;i<a.size();) { a[i].write_value(out,tabs); i++; if(i<a.size()) indent(out,',',tabs); } indent(out,']',tabs); } break; case json::is_object: { json::object const &obj=object(); object::const_iterator p,end; p=obj.begin(); end=obj.end(); indent(out,'{',tabs); while(p!=end) { out<<escape(p->first); indent(out,':',tabs); p->second.write_value(out,tabs); ++p; if(p!=end) indent(out,',',tabs); } indent(out,'}',tabs); } break; default: throw bad_value_cast("Unknown type found: internal error"); } }
上面的代码包含了很多细节,很多都可以独立成文描述。这里主要是为了搞明白cppcms::json::value内部的设计原理,便于更好的使用。就暂时追踪到这里。
下面的代码演示了如何将流里面的JSON串放入value对象,然后通过get方法查找,"null"是假定找不到的时候的默认值。
stringstream stream; stream << "{\"message\":\"ok\",\"status\":0}"; cppcms::json::value value2; stream >> value2; string m = value2.get("message","null");
/// /// Get an object of type T from the path \a path. Throws bad_value_cast if such path does not /// exists of conversion can't be done /// template<typename T> T get(std::string const &path) const { return at(path).get_value<T>(); }