JSON 在C++中的使用

长平狐 发布于 2012/08/28 16:36
阅读 1K+
收藏 1

CppCMS的编译和使用

请参考我的相关文章。

将C++对象转换成JSON字符串

假定有一个类response,两个字段,一个是status,0代表正确。其他代表错误。另一个是message字段,表示操作结果的具体信息。代码如下:

class response {
public:
    //0 is ok
    //other values are wrong
    int status;
    string message;
};

现在需要将response对象的数据转换成JSON格式字符串。还需要写一个模板类来,代码如下:

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;
}

运行结果:
{"message":"ok","status":0}
{"message":"unknown error","status":1}

cppcms::json::value类代码分析

之所以很容易就转换成JSON串,是因为使用了value类。现在来分析一下上面的调用代码里面是如何工作的。
1.cppcms::json::value(r1) 创建了匿名对象value,value的构造函数内部调用了set_value方法。参数v此时就是response对象。


template<typename T>
        value(T const &v)
        {
                set_value(v);
        }

2.set_value方法调用了traits<T>::set( this,v),这个就是前面我们重载的模板方法。

template<typename T>
        void set_value(T const &v)
        {
                traits<T>::set(this,v);
        }

3.剩下的事情目的很明确了,需要将value对象的值转换成JSON字符串,然后输出到流中。Artyom重载了operator<<函数,底层实现函数如下:

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字符串转换成C++对象

下面的代码演示了如何将流里面的JSON串放入value对象,然后通过get方法查找,"null"是假定找不到的时候的默认值。

stringstream stream;
    stream << "{\"message\":\"ok\",\"status\":0}";

    cppcms::json::value value2;
    stream >> value2;
    string m = value2.get("message","null");

也可以用更严格的get方法的重载,没有默认值,如果找不到就会抛出bad_cast异常。

///
        /// 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>();
        }

我不喜欢写篇幅很大的文章,本篇主要描述如何使用,顺便挖了一下源代码。后面会陆续深挖CppCMS的源代码。



原文链接:http://blog.csdn.net/sheismylife/article/details/7096228
加载中
返回顶部
顶部