怎样写一个好用的C++ Json解析器?

之前用RapidJson来做json的解析,但是,RapidJson还是有麻烦的地方,虽然速度非常快,但是由于用了非常多的优化技巧,反而无法做到我想要的那种简便的访问方式。

比如,有这么一个字符串:

"{ \"a\":1000,\"b\":30000,\"c\":[123,456,789,5555, 1.0e2, true, false, null, \"test\", \"big big world\"]}"

我在C++里面需要非常简单的使用它,例如这样:

		static char text[] = "{ \"a\":1000,\"b\":30000,\"c\":[123,456,789,5555, 1.0e2, true, false, null, \"test\", \"big big world\"]}";
		atom::CJson root = text;

		root["a"] = 123;
		root["c"] = true;
		root["b"] = "b is the biggest";
		atom::CJson test = "{\"new key\": 1037, 'test-key':1234e-5, 'array':[1,2,3,1,1,0] }";
		root["e"] = test;
		test["array"][0] = 1000;

		atom::a_string value = root.Stringity();
		printf( "%s\n", value.c_str() );

而输出结果如下:

{"a":123, "b":"b is the biggest", "c":1, "e":{"new key":1037, "test-key":0.012340, "array":[1000, 2, 3, 1, 1, 0, ], }, }

找了几个Json库,似乎都没有我想要的那种效果。快的访问很麻烦,访问方便点的速度又上不去。后来还是决定自己写一个。

自己写出来后,测试了一下,在不开优化的情况下,时间开销大概是RapidJson的8倍,如果开编译器优化,则时间开销是RapidJson的4倍左右。其实还是有可以再优化的地方,但再优化就必须要损失易用性为代价。想了一下,还是放弃了,这个解析速度和访问的方便程度我已经很满意了。

而且我自己写的Json还能支持序列化到流数据,如果采用这个方式,恢复的速度和RapidJson的解析差不多。

代码如下:有兴趣的可以参考。

tokenizer数据结构的头文件和cpp文件

#ifndef TAGJSONTOKEN_H
#define TAGJSONTOKEN_H
//Begin section for file tagJsonToken.h
//TODO: Add definitions that you want preserved
//End section for file tagJsonToken.h
#include "../stl/a_string.h"
#include "../stl/allocator.h"
#include "../tool/CVariablePtr.h"



namespace atom
{




    //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
    struct tagJsonToken
    {

        //Begin section for atom::tagJsonToken
        //TODO: Add attributes that you want preserved
        //End section for atom::tagJsonToken

        public:


            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            //typedef CVariablePtr<tagJsonToken>  Ptr ;



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            typedef vector<tagJsonToken, atom_allocator<tagJsonToken> >  Array ;



        public:


            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            U32 token;



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            size_t start;



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            size_t close;



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            tagJsonToken(); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            tagJsonToken(const tagJsonToken & value); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            tagJsonToken(U32 token); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            tagJsonToken(U32 token, size_t start, size_t close); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            ~tagJsonToken(); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            tagJsonToken & operator=(const tagJsonToken & value); 



    };  //end struct tagJsonToken



} //end namespace nova



#endif
#include "tagJsonToken.h"
//Begin section for file tagJsonToken.cpp
//TODO: Add definitions that you want preserved
//End section for file tagJsonToken.cpp


//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::tagJsonToken::tagJsonToken() : 
token(0),start(0),close(0)
{
    //TODO Auto-generated method stub
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::tagJsonToken::tagJsonToken(const tagJsonToken & in) : 
token(in.token),start(in.start),close(in.close)
{
    //TODO Auto-generated method stub
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::tagJsonToken::tagJsonToken(U32 t) : 
token(t),start(0),close(0)
{
    //TODO Auto-generated method stub
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::tagJsonToken::tagJsonToken(U32 t, size_t s, size_t c) : 
token(t),start(s),close(c)
{
    //TODO Auto-generated method stub
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::tagJsonToken::~tagJsonToken() 
{
    //TODO Auto-generated method stub
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::tagJsonToken & atom::tagJsonToken::operator=(const tagJsonToken & in) 
{
    //TODO Auto-generated method stub
    token = in.token;
    start = in.start;
    close = in.close;
    return( * this );
}

json节点的头文件和cpp文件

#ifndef TAGJSONKEYVALUE_H
#define TAGJSONKEYVALUE_H
//Begin section for file tagJsonKeyValue.h
//TODO: Add definitions that you want preserved
//End section for file tagJsonKeyValue.h
#include "../stl/a_string.h"
#include "../stl/stl_extend.h"
#include "../variant/CVariant.h"
#include "../tool/CVariablePtr.h"



namespace atom
{



    //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
    struct tagJsonKeyValue
    {

        //Begin section for atom::tagJsonKeyValue
        //TODO: Add attributes that you want preserved
        //End section for atom::tagJsonKeyValue

        public:


            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            typedef CVariablePtr<tagJsonKeyValue>  Ptr ;


            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            typedef vector<pair<size_t, tagJsonKeyValue::Ptr>, atom_allocator<pair<size_t, tagJsonKeyValue::Ptr> > >  Array ;




        public:


            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            a_string index;



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            CVariant value;



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            Array group;



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            //Map query;



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            tagJsonKeyValue(); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            tagJsonKeyValue(const char * value); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            tagJsonKeyValue(const CVariant & data); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            tagJsonKeyValue(const char * value, const CVariant & data); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            tagJsonKeyValue(const tagJsonKeyValue & value); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            ~tagJsonKeyValue(); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            tagJsonKeyValue & operator=(const tagJsonKeyValue & value); 



    };  //end struct tagJsonKeyValue



} //end namespace atom



template<class Archive>
inline void Serialize(Archive & archive, atom::tagJsonKeyValue & value, bool isSave)
{
    UNREFERENCED_PARAMETER( isSave );
    archive.Bind( value.index );
    archive.Bind( value.value );
    archive.Bind( value.group );
}



#endif
#include "tagJsonKeyValue.h"
//Begin section for file tagJsonKeyValue.cpp
//TODO: Add definitions that you want preserved
//End section for file tagJsonKeyValue.cpp


//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::tagJsonKeyValue::tagJsonKeyValue() 
{
    //TODO Auto-generated method stub
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::tagJsonKeyValue::tagJsonKeyValue(const char * in):
index(in ? in : "")
{
    //TODO Auto-generated method stub
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::tagJsonKeyValue::tagJsonKeyValue(const CVariant & in) :
value(in)
{
    //TODO Auto-generated method stub
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::tagJsonKeyValue::tagJsonKeyValue(const char * in_1, const CVariant & in_2) :
index(in_1 ? in_1 : ""),value(in_2)
{
    //TODO Auto-generated method stub
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::tagJsonKeyValue::tagJsonKeyValue(const tagJsonKeyValue & in) :
index(in.index),value(in.value),group(in.group)
{
    //TODO Auto-generated method stub
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::tagJsonKeyValue::~tagJsonKeyValue() 
{
    //TODO Auto-generated method stub
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::tagJsonKeyValue & atom::tagJsonKeyValue::operator=(const tagJsonKeyValue & in) 
{
    //TODO Auto-generated method stub
    index = in.index;
    value = in.value;
    group = in.group;
    return( * this );
}

接下来是 Tokenizer 的实现

#include "CJsonTokenizer.h"
#include "../../enumeration/JSON_TOKEN.h"
//Begin section for file CJsonTokenizer.cpp
//TODO: Add definitions that you want preserved
//End section for file CJsonTokenizer.cpp



//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::CJsonTokenizer::CJsonTokenizer() 
{
    //TODO Auto-generated method stub
    tokens.reserve( 1024 );
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::CJsonTokenizer::~CJsonTokenizer() 
{
    //TODO Auto-generated method stub
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJsonTokenizer::Start(const char * json) 
{
    //TODO Auto-generated method stub
    if( json == NULL ) {
        return false;
    }

    size_t offset = 0;
    size_t length = strlen( json );

    buffer.Alloc( length );
    if( buffer ) {
        buffer.Store( json, length );
    }

    bool result = true;
    for( ;; )
    {
        // skip any reserved or space characters.
        for( ; IsSpace(json, offset, length); ++ offset );

        // offset check
        if( offset >= length )
        {
            tokens.push_back( tagJsonToken() );
            tokens.back().token = JT_END;
            break;
        }

        char c = json[offset];

        // create token
        if( IsNull(json, offset, length) )
        {
            offset += 4;
            tokens.push_back( tagJsonToken(JT_NULL) );
        }
        else
        if( c == ',' )
        {
            offset += 1;
            tokens.push_back( tagJsonToken(JT_COMMA) );
        }
        else
        if( c == ':' )
        {
            offset += 1;
            tokens.push_back( tagJsonToken(JT_COLON) );
        }
        else
        if( c == '{' )
        {
            offset += 1;
            tokens.push_back( tagJsonToken(JT_OBJECT_BEGIN) );
        }
        else
        if( c == '[' )
        {
            offset += 1;
            tokens.push_back( tagJsonToken(JT_ARRAY_BEGIN) );
        }
        else
        if( c == ']' )
        {
            offset += 1;
            tokens.push_back( tagJsonToken(JT_ARRAY_CLOSE) );
        }
        else
        if( c == '}' )
        {
            offset += 1;
            tokens.push_back( tagJsonToken(JT_OBJECT_CLOSE) );
        }
        else
        if( IsTrue(json, offset, length) )
        {
            offset += 4;
            tokens.push_back( tagJsonToken(JT_BOOL, 1, 0) );
        }
        else
        if( IsFalse(json, offset, length) )
        {
            offset += 5;
            tokens.push_back( tagJsonToken(JT_BOOL) );
        }
        else
        if( c == '\'' || c == '\"' )
        {
            // read string will modify the offset;
            size_t start(0), close(0);
            ReadString( json, offset, length, start, close );

            if( start == 0 || close == 0 || close <= start ) 
            {
                char msg[32];
                sprintf( msg, "%zu", offset );

                errmsg = "Failed read string from offset ";
                errmsg = errmsg + msg;

                tokens.clear();
                result = false;
                break;
            }

            tokens.push_back( tagJsonToken(JT_STRING, start, close) );
        }
        else
        if( IsNumber(json, offset, length) )
        {
            size_t start(0), close(0);
            ReadNumber( json, offset, length, start, close );

            // read number will modify the offset;
            if( start == 0 || close == 0 || close <= start ) 
            {
                char msg[32];
                sprintf( msg, "%zu", offset );

                errmsg = "Failed read number from offset ";
                errmsg = errmsg + msg;

                tokens.clear();
                result = false;
                break;
            }

            tokens.push_back( tagJsonToken(JT_NUMBER, start, close) );
        }
        else
        {
            char msg[32];
            sprintf( msg, "%zu", offset );

            errmsg = "Invalid char at offset ";
            errmsg = errmsg + msg;

            tokens.clear();
            result = false;
            break;
        }
    }
    return result;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJsonTokenizer::IsNull(const char * json, size_t & offset, size_t length) 
{
    //TODO Auto-generated method stub
    bool result = false;
    if( json )
    {
        // length must enough.
        if( (length - offset) + 1 >= 4 )
        {
            const char * site = json + offset;
            if( *site == 'n' || *site == 'N' )
            {
                ++ site;
                if( *site == 'u' || *site == 'U' )
                {
                    ++ site;
                    if( *site == 'l' || *site == 'L' )
                    {
                        ++ site;
                        if( *site == 'l' || *site == 'L' )
                        {
                            result = true;
                        }
                    }
                }
            }
        }
    }
    return result;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJsonTokenizer::IsTrue(const char * json, size_t & offset, size_t length) 
{
    //TODO Auto-generated method stub
    bool result = false;
    if( json )
    {
        // length must enough.
        if( (length - offset) + 1 >= 4 )
        {
            const char * site = json + offset;
            if( *site == 't' || *site == 'T' )
            {
                ++ site;
                if( *site == 'r' || *site == 'R' )
                {
                    ++ site;
                    if( *site == 'u' || *site == 'U' )
                    {
                        ++ site;
                        if( *site == 'e' || *site == 'E' )
                        {
                            result = true;
                        }
                    }
                }
            }
        }
    }
    return result;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJsonTokenizer::IsFalse(const char * json, size_t & offset, size_t length) 
{
    //TODO Auto-generated method stub
    bool result = false;
    if( json )
    {
        // length must enough.
        if( (length - offset) + 1 >= 5 )
        {
            const char * site = json + offset;
            if( *site == 'f' || *site == 'F' )
            {
                ++ site;
                if( *site == 'a' || *site == 'A' )
                {
                    ++ site;
                    if( *site == 'l' || *site == 'L' )
                    {
                        ++ site;
                        if( *site == 's' || *site == 'S' )
                        {
                            ++ site;
                            if( *site == 'e' || *site == 'E' )
                            {
                                result = true;
                            }
                        }
                    }
                }
            }
        }
    }
    return result;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJsonTokenizer::IsSpace(const char * json, size_t & offset, size_t length) 
{
    //TODO Auto-generated method stub
    if( !json ) {
        return false;
    }

    bool result = false;
    if( offset < length )
    {
        if( json[offset] <= 0x20 )
        {
            result = true;
        }
    }
    return result;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJsonTokenizer::IsNumber(const char * json, size_t & offset, size_t length) 
{
    //TODO Auto-generated method stub
    if( !json ) {
        return false;
    }

    bool result = false;
    if( offset < length )
    {
        char c = json[offset];
        result = IsDigit( c ) || c == '-';
    }
    return result;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJsonTokenizer::IsEscape(const char * json, size_t & offset, size_t length) 
{
    //TODO Auto-generated method stub
    if( !json ) {
        return false;
    }

    bool result = false;
    if( offset < length )
    {
        char c = json[offset];
        if( c == '\"' || c == '\\' || c == '/' ||
            c == 'b'  || c == 'f'  || c == 'n' ||
            c == 't'  || c == 'r'  || c == 'u' )
        {
            result = true;
        }
    }
    return result;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJsonTokenizer::ReadNumber(const char * json, size_t & offset, size_t length, size_t & start, size_t & close) 
{
    //TODO Auto-generated method stub
    if( !json ) {
        return false;
    }

    if( offset >= length ) {
        return false;
    }

    size_t backup = offset;

    start = offset;
    close = offset;

    if( json[offset] == '-' ) 
    {
        ++ close; ++ offset;
    } 

    char c = 0;
    bool succeed = true;

    // read integer part
    
    size_t bias(0); bool stop(false);
    for( ;; ++ bias ) 
    {
        if( offset == length ) {
            break;
        }

        if( offset  > length ) {
            succeed = false;
            break;
        }

        c = json[offset];

        // stop flag
        if( stop == true ) {
            break;
        }

        // if 0 is the first digit.
        if( bias == 0 && c == '0' )
        {
            ++ close; ++ offset;
            stop = true;
            continue;
        }

        if( IsDigit(c) )
        {
            ++ close; ++ offset;
            continue;
        }

        // The first char is illegal, set failed.
        if( bias == 0 ) {
            succeed = false;
        }

        // if c is not digit, break;
        break;
    }

    if( succeed && 
        offset == length ) {
        return true;
    }

    // read frac part
    if( succeed && c == '.' )
    {
        ++ close; ++ offset;

        bias = 0;
        for( ;; ++ bias ) 
        {
            if( offset == length ) {
                break;
            }

            if( offset  > length ) {
                succeed = false;
                break;
            }

            c = json[offset];

            if( IsDigit(c) )
            {
                ++ close; ++ offset;
                continue;
            }

            if( bias == 0 ) {
                succeed = false;
            }

            // if c is not digit, break;
            break;
        }
    }

    if( succeed && 
        offset == length ) {
        return true;
    }

    // read exp part
    if( succeed && (
        c == 'e' || c == 'E' ) )
    {
        ++ close; ++ offset;

        bias = 0;
        for( ;; ++ bias ) 
        {
            if( offset == length ) {
                break;
            }

            if( offset  > length ) {
                succeed = false;
                break;
            }

            c = json[offset];

            if( c == '-' )
            {
                if( bias == 0 )
                {
                    ++ close; ++ offset;
                    continue;
                }
                else
                {
                    succeed = false;
                    break;
                }
            }

            if( IsDigit(c) )
            {
                ++ close; ++ offset;
                continue;
            }

            if( bias == 0 ) {
                succeed = false;
            }

            // if c is not digit, break;
            break;
        }
    }

    if( succeed == false ) {
        offset = backup; start = close = 0;
    }
    return succeed;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJsonTokenizer::ReadString(const char * json, size_t & offset, size_t length, size_t & start, size_t & close) 
{
    //TODO Auto-generated method stub
    if( !json ) {
        return false;
    }

    if( offset >= length ) {
        return false;
    }

	size_t backup = offset;

	char quotation = 0;
	if (json[offset] == '\"' || json[offset] == '\'') {
        quotation = json[offset ++];
	}

    start = close = offset;

    char c;
    bool succeed = true; 

	for( ;; )
	{
        // check the offset.
        if( offset >= length ) 
        {
            succeed = false;
            break;
        }

		c = json[offset ++];

		// is escpae ? 
		if( c == '\\' )
		{
			if( !IsEscape(json, offset, length) )
			{
                succeed = false;
				break;
			}

			++ close;

            // because the IsEscape function already verified the 
            // offset range. so, here's offset is valid.
			c = json[offset ++];

			++ close;

            // Process Unicode,from \u0000 to \uffff
			if( c == 'u' ) 
            { 
                // memory border check
                if( length - offset + 1 < 4 ) {
                    succeed = false;
                    break;
                }

				for( size_t i = 0; i < 4; ++ i ) 
                {
					c = json[offset ++];

					if( IsHex(c) ) 
                    {
						++ close;
					}
					else 
                    {
						succeed = false;
                        break;
					}
				}

                // if failed to process Unicode, stop the main loop.
                if( !succeed ) break;
			}
		}

        // another quotation ? 
		else 
        if( c == quotation )
        { 
			break;
		}
		else 
        if( c == '\r' || c == '\n') 
        {
            succeed = false;
            break;
		}
		else 
        {
			++ close;
		}
	}

    // 如果失败,则清理现场
    if( succeed == false ) {
	    offset = backup; start = close = 0;
    }

    return succeed;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::tagJsonToken::Array & atom::CJsonTokenizer::GetTokens() 
{
    //TODO Auto-generated method stub
    return tokens;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::a_string atom::CJsonTokenizer::GetError() 
{
    //TODO Auto-generated method stub
    return errmsg;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
const char * atom::CJsonTokenizer::GetString(size_t start, size_t close)
{
    //TODO Auto-generated method stub
    static char text[] = "";
    size_t length = buffer.GetLength();
    if( start < length && close < length && close > start ) 
    {
        buffer.Query<char>()[close] = 0;
        return & buffer.Query<char>()[start];
    }
    return text;
}

Parser的实现:

#include "CJsonParser.h"
#include "CJsonTokenizer.h"
#include "../stl/string_splite.h"
#include "../../enumeration/JSON_TOKEN.h"
//Begin section for file CJsonParser.cpp
//TODO: Add definitions that you want preserved
//End section for file CJsonParser.cpp


//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::CJsonParser::CJsonParser() 
{
    //TODO Auto-generated method stub
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::CJsonParser::~CJsonParser() 
{
    //TODO Auto-generated method stub
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJsonParser::Parse(const char * text, CJson & json) 
{
    //TODO Auto-generated method stub
    if( text == NULL ) {
        error = "Invalid arguments";
        return false;
    }

    bool result = false;
    CJsonTokenizer tokenizer;
    
    if( tokenizer.Start(text) == false ) {
        error = tokenizer.GetError();
        return false;
    }

    if( tokenizer.GetTokens().empty() ) {
        error = "Empty json string";
        return false;
    }

    size_t offset   = 0;
    U32 begin_token = tokenizer.GetTokens().front().token;
    if( begin_token == JT_ARRAY_BEGIN  )
    {
        result = ParseArray  ( tokenizer, offset, json );
    }
    else
    if( begin_token == JT_OBJECT_BEGIN )
    {
        result = ParseObject ( tokenizer, offset, json );
    }
    else
    if( IsPrimary(begin_token) )
    {
        CVariant data;
        result = ParsePrimary( tokenizer, offset, data );

        if( result ) 
        {
            // 一开始就是原型的字符串必须立即结束
            if( tokenizer.GetTokens().size() <= offset || 
                tokenizer.GetTokens().at(offset).token == JT_END )
            {
                json = data;
            }
            else
            {
                error  = "Json should ended after the 1st element"; 
                result = false;
            }
        }
    }
    return result;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::a_string atom::CJsonParser::GetError() 
{
    //TODO Auto-generated method stub
    return error;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJsonParser::IsPrimary(U32 type) 
{
    //TODO Auto-generated method stub
    return 
        type == JT_BOOL   || type == JT_NULL || 
        type == JT_NUMBER || type == JT_STRING;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJsonParser::ParseArray(CJsonTokenizer & tokenizer, size_t & offset, CJson & node) 
{
    //TODO Auto-generated method stub
    tagJsonToken::Array & tokens = tokenizer.GetTokens();
    if( offset >= tokens.size() ) {
        error = "Invalid offset";
        return false;
    }

    if( tokens[offset].token != JT_ARRAY_BEGIN ) {
        error = "Invalid array token";
        return false;
    }

    size_t backup = offset;

    // consume [
    ++ offset;

    bool result = true;
    for( ;; )
    {
        if( offset >= tokens.size() ) 
        {
            error  = "Tokens not complete"; 
            result = false;
            break;
        }

        if( tokens[offset].token == JT_ARRAY_CLOSE )
        {
            ++ offset;  // consume ]
            break;
        }

        if( tokens[offset].token == JT_ARRAY_BEGIN  )
        {
            CJson data;
            if( false == 
                ParseArray(tokenizer, offset, data) ) 
            {
                result = false;
                break;
            }

            node.Push( data );
        }
        else
        if( tokens[offset].token == JT_OBJECT_BEGIN )
        {
            CJson data;
            if( false == 
                ParseObject(tokenizer, offset, data) ) 
            {
                result = false;
                break;
            }

            node.Push( data );
        }
        else
        if( tokens[offset].token == JT_COMMA )
        {
            ++ offset;
        }
        else 
        if( IsPrimary(tokens[offset].token) )
        {
            CVariant data;
            if( false == 
                ParsePrimary(tokenizer, offset, data) ) 
            {
                result = false;
                break;
            }

            node.Push( data );
        }
        else
        {
            error  = "Invalid token in array";
            result = false;
            break;
        }
    }

    if( result == false ) {
        offset = backup;
    }
    return result;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJsonParser::ParseObject(CJsonTokenizer & tokenizer, size_t & offset, CJson & node) 
{
    //TODO Auto-generated method stub
    tagJsonToken::Array & tokens = tokenizer.GetTokens();
    if( offset >= tokens.size() ) {
        error = "Invalid offset";
        return false;
    }

    if( tokens[offset].token != JT_OBJECT_BEGIN ) 
    {
        error = "Invalid object token";
        return false;
    }

    size_t backup = offset;

    // consume {
    ++ offset;

    bool result = true;
    for( ;; )
    {
        if( offset >= tokens.size() ) 
        {
            error  = "Tokens not complete"; 
            result = false;
            break;
        }

        if( tokens[offset].token == JT_OBJECT_CLOSE )
        {
            ++ offset;  // consume }
            break;
        }

        if( tokens[offset].token == JT_COMMA )
        {
            ++ offset;  // consume ,
            continue;
        }

        // 读key,key必须是string类型
        if( tokens[offset].token != JT_STRING )
        {
            error  = "Invalid key token type";
            result = false;
            break;
        }

        // 创建对象的键值对。
        CJson value = node[
            tokenizer.GetString(
            tokens[offset].start, 
            tokens[offset].close)]; 
        ++ offset;

        if( offset >= tokens.size() ) 
        {
            error  = "Tokens not complete"; 
            result = false;
            break;
        }

        if( tokens[offset].token != JT_COLON )
        {
            error  = "Invalid splite token type";
            result = false;
            break;
        }

        ++ offset;  // consume :

        if( offset >= tokens.size() ) 
        {
            error  = "Tokens not complete"; 
            result = false;
            break;
        }

        if( IsPrimary(tokens[offset].token) )
        {
            CVariant data;
            if( false == 
                ParsePrimary(tokenizer, offset, data) ) 
            {
                result = false;
                break;
            }

            value = data;
        }
        else
        if( tokens[offset].token == JT_ARRAY_BEGIN  )
        {
            CJson data;
            if( false == 
                ParseArray(tokenizer, offset, data) ) 
            {
                result = false;
                break;
            }

            value = data;
        }
        else
        if( tokens[offset].token == JT_OBJECT_BEGIN )
        {
            CJson data;
            if( false == 
                ParseObject(tokenizer, offset, data) ) 
            {
                result = false;
                break;
            }

            value = data;
        }
        else 
        {
            error  = "Invalid value token type";
            result = false;
            break;
        }
    }

    if( result == false ) {
        offset = backup;
    }
    return result;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJsonParser::ParsePrimary(CJsonTokenizer & tokenizer, size_t & offset, CVariant & data) 
{
    //TODO Auto-generated method stub
    tagJsonToken::Array & tokens = tokenizer.GetTokens();
    if( offset >= tokens.size() ) {
        error = "Invalid offset";
        return false;
    }

    bool result = true;
    switch( tokens[offset].token )
    {
    case JT_NUMBER:
        {
            const char * value = tokenizer.GetString( 
                tokens[offset].start, 
                tokens[offset].close );

            size_t length = strlen( value );
            size_t splite = 0;
            for( size_t i = 0; i < length; ++ i )
            {
                if( value[i] == 'e' || value[i] == 'E' ) {
                    splite = i;
                }
            }

            // only one part.
            if( length > 0 )
            {
                // 先计算指数
                char * stop = NULL;

                I64 exp = 0;
                if( splite != 0 )
                {
                    #if defined(_WIN32)
                    exp = static_cast<I64>( _strtoi64( & value[splite + 1], & stop, 10 ) );
                    #else
                    exp = static_cast<I64>(  strtoll ( & value[splite + 1], & stop, 10 ) );
                    #endif
                }

                if( splite == 0 )
                {
                    splite = length;
                }

                bool is_float = false;
                for( size_t i = 0; i < splite; ++ i )
                {
                    if( value[i] == '.' ) {
                        is_float = true;
                    }
                }

                // 再判断前面部分
                if( is_float == false )
                {
                    #if defined(_WIN32)
                    I64 integer = static_cast<I64>( _strtoi64( value, & stop, 10 ) );
                    #else
                    I64 integer = static_cast<I64>(  strtoll ( value, & stop, 10 ) );
                    #endif

                    double range = integer * pow( 10, exp );

                    abs( range - static_cast<I64>(range) ) < 1e-6 ?
                        data = static_cast<I64>(range):
                        data = range;

                    ++ offset;
                }
                else
                {
                    double decimal = strtod( value, & stop );
                    double range = decimal * pow( 10, exp );
                    
                    abs( range - static_cast<I64>(range) ) < 1e-6 ?
                        data = static_cast<I64>(range):
                        data = range;

                    ++ offset;
                }
            }
            else 
            {
                error  = "Invalid number format";
                result = false;
            }
        }
        break;
    case JT_STRING:
        {
            data = tokenizer.GetString( 
                tokens[offset].start, 
                tokens[offset].close );
            ++ offset;
        }
        break;
    case JT_NULL:
        {
            data.Clear(); ++ offset;
        }
        break;
    case JT_BOOL:
        {
            bool value = tokens[offset ++].start == 1;
            data = value;
        }
        break;
    default:
        error = "Not primary"; result = false;
        break;
    }
    return result;
}

最后的重点:CJson 类的实现:

#ifndef CJSON_H
#define CJSON_H
//Begin section for file CJson.h
//TODO: Add definitions that you want preserved
//End section for file CJson.h
#include "tagJsonKeyValue.h"
#include "../variant/CVariant.h"



namespace atom
{



    //<p>This class is not thread safe. Should used under critical section's protection.</p>
    //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
    class CJson
    {

        //Begin section for atom::CJson
        //TODO: Add attributes that you want preserved
        //End section for atom::CJson

        private:


            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            mutable tagJsonKeyValue::Ptr root;



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            mutable U08 type;



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            U08 CheckType(const tagJsonKeyValue::Ptr & node); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            bool Assign(U08 in_type, const tagJsonKeyValue::Ptr & in, bool & deep);




        public:

            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            CJson(); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            CJson(const CJson & value); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            CJson(const tagJsonKeyValue::Ptr & value); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            CJson(const char * value); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            operator CVariant() const; 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            CJson & operator=(const CJson & value); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            CJson & operator=(const CVariant & value); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            CJson & operator=(const tagJsonKeyValue::Ptr & value); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            CJson & operator=(const char * value); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            CJson operator[](I32 offset); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            CJson operator[](size_t offset); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            CJson operator[](const char * index); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            size_t Length(); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            U08 GetType(); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            bool Push(const CVariant & data); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            bool Push(const CJson & data); 



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            a_string Stringity();



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            a_string Stringity(const tagJsonKeyValue::Ptr & value);



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            CJson Clone();



            //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
            tagJsonKeyValue Clone(const tagJsonKeyValue::Ptr & value);



            template<class A>
            inline void Serialize(A & ar, bool save)
            {
	            ar.Bind( type );
	            ar.Bind( root );
            }



    };  //end class CJson



} //end namespace atom



#endif

#include "CJson.h"
#include "CJsonParser.h"
#include "../stl/stl_extend.h"
#include "../../enumeration/JSON_VALUE_TYPE.h"
#include "../../enumeration/VARIANT_TYPE.h"
//Begin section for file CJson.cpp
//TODO: Add definitions that you want preserved
//End section for file CJson.cpp


//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::CJson::CJson() :
type(JVT_NONE)
{
    //TODO Auto-generated method stub
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::CJson::CJson(const CJson & value) :
root(value.root),type(value.type)
{
    //TODO Auto-generated method stub
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::CJson::CJson(const tagJsonKeyValue::Ptr & value) :
type(JVT_NONE)
{
    //TODO Auto-generated method stub
    * this = value;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::CJson::CJson(const char * value) :
type(JVT_NONE)
{
    //TODO Auto-generated method stub
    * this = value;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJson::Assign(U08 in_type, const tagJsonKeyValue::Ptr & in, bool & deep)
{
    //TODO Auto-generated method stub
    if( root == NULL ) {
        root = tagJsonKeyValue();
    }

    if( root == NULL ) {
        return false;
    }

    // 对不同的类型有不同的设置方式;
    // 此处是深度复制,是否需要浅层复制?
    deep = true;
    switch( type )
    {
    case JVT_OBJECT:
    case JVT_ARRAY:
        root -> group.clear();
    case JVT_NONE:
    case JVT_PRIMARY:
        root -> value.Clear();
        root -> index = in -> index;
        root -> value = in -> value;
        root -> group = in -> group;
        type = in_type;
        break;
    case JVT_PAIR:
        switch( in_type )
        {
        case JVT_NONE:
        case JVT_PRIMARY:
            root -> value.Clear();
            if( in ) {
                root -> value = in -> value;
                type = JVT_PRIMARY;
            }
            break;
        case JVT_OBJECT:
            type = JVT_OBJECT;
            root -> group.clear();
            if( in ) {
                root -> group = in -> group;
            }
            break;
        case JVT_ARRAY:
            type = JVT_ARRAY;
            root -> group.clear();
            if( in ) {
                root -> group = in -> group;
            }
            break;
        case JVT_PAIR:
            type = JVT_OBJECT;
            root -> value.Clear();
            root -> group.clear();

            if( in )
            {
                atom_hash<const char *> hasher;
                root -> group.push_back( make_pair(
                    hasher( in -> index.c_str() ), in) );

                // 唯有插入pair变成object时,才是浅层复制
                deep = false;
            }
        }
        break;
    }
    return true;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::CJson & atom::CJson::operator=(const CJson & in) 
{
    //TODO Auto-generated method stub
    bool deep = false;
    if( Assign(in.type, in.root, deep) )
    {
        if( deep )
        {
            in.root -> index = root -> index;
            in.root -> value = root -> value;
            in.root -> group = root -> group;
            in.type = type;
        }
    }
    return( * this );
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::CJson & atom::CJson::operator=(const tagJsonKeyValue::Ptr & in) 
{
    //TODO Auto-generated method stub
    // 该函数直接赋值,因为这个函数仅仅是在Parse时调用
    root = in;
    type = CheckType( in );
    return( * this );
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::CJson & atom::CJson::operator=(const CVariant & value)
{
    //TODO Auto-generated method stub
    // 如果为空,则赋予初值
    if( root == NULL ) {
        root = tagJsonKeyValue();
    }

    if( root == NULL ) {
        return( * this );
    }

    // 对不同的类型有不同的设置方式;
    switch( type )
    {
    case JVT_OBJECT:
    case JVT_ARRAY:
        root -> group.clear();

    case JVT_NONE:
    case JVT_PRIMARY:
        root -> value = value;
        type = JVT_PRIMARY;
        break;
    case JVT_PAIR:
        root -> value = value;
        break;
    }
    return( * this );
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::CJson & atom::CJson::operator=(const char * value)
{
    //TODO Auto-generated method stub
    if( value )
    {
        CJsonParser parser; CJson node;
        if( parser.Parse(value, node) ) {
            * this = node;
        } else {
            * this = CVariant( value );
        }
    }
    return( * this );
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::CJson atom::CJson::operator[](I32 offset) 
{
    //TODO Auto-generated method stub
    return this -> operator[]( static_cast<size_t>(offset) );
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::CJson atom::CJson::operator[](size_t offset) 
{
    //TODO Auto-generated method stub
    if( root && type == JVT_ARRAY )
    {
        if( offset < root -> group.size() )
        {
            return CJson( root -> group[offset].second );
        }
    }
    return CJson();
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::CJson atom::CJson::operator[](const char * index) 
{
    //TODO Auto-generated method stub
    // 访问类成员,本身不能是数组,也就是说root的大小必须为1
    // 然后这个index必须存在。
    if( !index ) {
        return CJson();
    }

    // 如果为空,则初始化一个
    if( root == NULL ) {
        root = tagJsonKeyValue();
        root -> group.reserve( 32 );
    }

    if( root == NULL ) {
        return CJson();
    }

    // 任何类型,都强制转换为object,然后重新设置
    switch( type )
    {
    case JVT_ARRAY:
        root -> group.clear();
    case JVT_PAIR:
        root -> index.clear();
    case JVT_PRIMARY:
        root -> value.Clear();
    case JVT_NONE:
        type = JVT_OBJECT;
        break;
    case JVT_OBJECT:
        break;
    }

    atom_hash<const char *> hasher;
    size_t key = hasher( index );

    bool finded = false;
    for( tagJsonKeyValue::Array::iterator
        it  = root -> group.begin();
        it != root -> group.end(); ++ it )
    {
        if( it -> first != key ) {
            continue;
        }

        // 必须判断 it second 内是否有值
        if( it -> second != NULL )
        {
            finded = true;
            return CJson( it -> second );
        }
    }

    if( finded == false )
    {
        root -> group.push_back(
            make_pair( key, tagJsonKeyValue(index) ) );

        // return directly
        return CJson( root -> group.back().second );
    }
    return CJson();
}

namespace atom
{



    //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
    CJson::operator CVariant() const
    {
        //TODO Auto-generated method stub
        if( root && 
            type == JVT_PRIMARY || 
            type == JVT_PAIR ) 
        {
            return CVariant( root -> value );
        }
        return CVariant();
    }



}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
U08 atom::CJson::CheckType(const tagJsonKeyValue::Ptr & node)
{
    //TODO Auto-generated method stub
    U08 result = JVT_NONE;
    if( node )
    {
        if( node -> group.empty() == false )
        {
            node -> group.front().first == 0 ? 
                result = JVT_ARRAY : 
                result = JVT_OBJECT;
        }
        else
        if( node -> index.empty() == false )
        {
            result = JVT_PAIR;
        }
        else
        {
            result = JVT_PRIMARY;
        }
    }
    return result;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
size_t atom::CJson::Length() 
{
    //TODO Auto-generated method stub
    size_t result = 0;
    if( root &&
        type == JVT_ARRAY ) {
        result = root -> group.size();
    }
    return result;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
U08 atom::CJson::GetType()
{
    //TODO Auto-generated method stub
    return type;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJson::Push(const CVariant & data) 
{
    //TODO Auto-generated method stub
    bool result = false;
    
    if( root == NULL ) {
        root = tagJsonKeyValue();
        root -> group.reserve( 32 );
    }

    if( root == NULL ) {
        return false;
    }

    result = true;

    switch( type )
    {
    case JVT_NONE:
        root -> group.push_back( 
            make_pair( 0, tagJsonKeyValue(data) ) );
        type = JVT_ARRAY;
        break;
    case JVT_PRIMARY:
        if( root -> value.Type() != VT_UNKNOW )
        {
            // 先把自己的值插进去
            root -> group.push_back( 
                make_pair( 0, tagJsonKeyValue(root -> value) ) );
            root -> value.Clear();

            root -> group.push_back( 
                make_pair( 0, tagJsonKeyValue(data) ) );
            type = JVT_ARRAY;
        }
        break;
    case JVT_PAIR:
        // 将pair的值变成数组
        root -> group.push_back( 
            make_pair( 0, tagJsonKeyValue(root -> value) ) );
        root -> value.Clear();

        root -> group.push_back( 
            make_pair( 0, tagJsonKeyValue(data) ) );
        type = JVT_ARRAY;
        break;
    case JVT_OBJECT:
        {
            // 将object的变成数组的第一个元素
            tagJsonKeyValue value;
            value.group = root -> group;

            // 清理掉原有的数据,再插入到数组中
            root -> group.clear();
            root -> group.push_back( make_pair(0, value) );

            value.group.clear();
            value.value = data;

            root -> group.push_back( make_pair(0, value) );
            type = JVT_ARRAY;
        }
        break;
    case JVT_ARRAY:
        root -> group.push_back( make_pair(0, tagJsonKeyValue(data) ) );
        break;
    default:
        result = false;
        break;
    }

    return result;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool atom::CJson::Push(const CJson & data) 
{
    //TODO Auto-generated method stub
    bool result = false;

    if( root == NULL ) {
        root = tagJsonKeyValue();
        root -> group.reserve( 32 );
    }

    if( root == NULL ) {
        return false;
    }

    if( data.root == NULL ) {
        return false;
    }

    // push a pair into array is not allowd
    if( data.root -> index.empty() == false ) {
        return false;
    }

    result = true;
    switch( type )
    {
    case JVT_NONE:
        {
            root -> group.push_back( make_pair(0, data.root) );
            type = JVT_ARRAY;
        }
        break;
    case JVT_PRIMARY:
        if( root -> value.Type() != VT_UNKNOW )
        {
            // push back self value first
            root -> group.push_back( 
                make_pair( 0, tagJsonKeyValue(root -> value) ) );
            root -> value.Clear();

            // push json object's value
            root -> group.push_back( 
                make_pair(0, data.root) );
            type = JVT_ARRAY;
        }
        break;
    case JVT_PAIR:
        {
            // convert pair's value as a array's element
            root -> group.push_back(
                make_pair( 0, tagJsonKeyValue(root -> value) ) );
            root -> value.Clear();

            root -> group.push_back( 
                make_pair( 0, data.root ) );
            type = JVT_ARRAY;
        }
        break;
    case JVT_OBJECT:
        {
            // push objct into array.
            tagJsonKeyValue value;
            value.group = root -> group;

            root -> group.clear();
            root -> group.push_back( make_pair(0, value) );
            root -> group.push_back( make_pair(0, data.root) );
            type = JVT_ARRAY;
        }
        break;
    case JVT_ARRAY:
        {
            root -> group.push_back( make_pair(0, data.root) );
        }
        break;
    default:
        result = false;
        break;
    }
    return result;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::a_string atom::CJson::Stringity()
{
    return Stringity( root );
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::a_string atom::CJson::Stringity(const tagJsonKeyValue::Ptr & value)
{
    a_string result;
    if( value )
    {
        U08 genre = CheckType( value );
        switch( genre )
        {
        case JVT_NONE:
            result += "null";
            break;
        case JVT_PAIR:
            result += "\"";
            result += value -> index;
            result += "\":";
        case JVT_PRIMARY:
            if( value -> value.Type() == VT_A_STR ||
                value -> value.Type() == VT_W_STR )
            {
                result += "\"";
                result += static_cast<const char *>( value -> value );
                result += "\"";
            }
            else
            {
                result += static_cast<const char *>( value -> value );
            }
            break;
        case JVT_ARRAY:
            if( value -> index.empty() == false ) 
            {
                result += "\"";
                result += value -> index;
                result += "\":";
            }
            
            result += "[";
            for( tagJsonKeyValue::Array::const_iterator 
                it  = value -> group.begin(); 
                it != value -> group.end(); ++ it )
            {
                if( it -> second )
                {
                    result += Stringity( it -> second );
                    result += ", ";
                }
            }
            result += "]";
            break;
        case JVT_OBJECT:
            if( value -> index.empty() == false ) 
            {
                result += "\"";
                result += value -> index;
                result += "\":";
            }

            result += "{";
            for( tagJsonKeyValue::Array::const_iterator 
                it  = value -> group.begin(); 
                it != value -> group.end(); ++ it )
            {
                if( it -> second )
                {
                    result += Stringity( it -> second );
                    result += ", ";
                }
            }
            result += "}";
            break;
        default:
            break;
        }
    }
    return result;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::CJson atom::CJson::Clone()
{
    CJson result;
    result.type = type;
    result.root = Clone( root );
    return result;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
atom::tagJsonKeyValue atom::CJson::Clone(const tagJsonKeyValue::Ptr & data)
{
    tagJsonKeyValue result;
    if( !data ) {
        return result;
    }

    result.index = data -> index;
    result.value = data -> value;
    
    // 先克隆下一层的数据;
    for( tagJsonKeyValue::Array::const_iterator
        it1  = data -> group.begin();
        it1 != data -> group.end(); ++ it1 )
    {
        result.group.push_back( 
            make_pair( it1 -> first, Clone(it1 -> second) ) );
    }
    return result;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JSON++ Build Status Introduction JSON++ is a light-weight JSON parser, writer and reader written in C++. JSON++ can also convert JSON documents into lossless XML documents. Contributors http://github.com/hjiang http://github.com/elanthis http://github.com/r-lyeh If you've made substantial contribution, please add your link here. Why another JSON parser? Perhaps because web service clients are usually written in dynamic languages these days, none of the existing C++ JSON parsers fitted my needs very well, so I wrote one that I used in another project. My goals for JSON++ were: Efficient in both memory and speed. No third party dependencies. JSON++ only depends on the standard C++ library. Cross platform. Robust. Small and convenient API. Most of the time, you only need to call one function and two function templates. Easy to integrate. JSON++ only has one source file and one header file. Just compile the source file and link with your program. Able to construct documents dynamically. JSON writer: write documents in JSON format. Other contributors have sinced added more functionalities: XML writer: convert documents to JSONx format. See http://goo.gl/I3cxs for details. XML writer: convert documents to JXML format. See https://github.com/r-lyeh/JXML for details. XML writer: convert documents to JXMLex format. See https://github.com/r-lyeh/JXMLex for details. XML writer: convert documents to tagged XML format. See https://github.com/hjiang/jsonxx/issues/12 for details. Compiler version You need a modern C++ compiler. For older compilers, please try legacy branch. Configuration Strict/permissive parsing JSONxx can parse JSON documents both in strict or permissive mode. When jsonxx::Settings::Parser is set to Strict, JSONxx parser will accept: Fully conformant JSON documents only. When jsonxx::Settings::Parser is set to Permissive, JSONxx parser will accept: Fully conformant JSON documents Ending commas in arrays and objects: { "array": [0,1,2,], } Single quoted strings: ['hello', "world"] C++ style comments: { "width": 320, "height": 240 } //Picture details Default value is Permissive. When jsonxx::Settings::UnquotedKeys is set to Enabled, JSONxx parser will accept: Unquoted keys: {name: "world"} Default value is Disabled. Assertions JSONxx uses internally JSONXX_ASSERT(...) macro that works both in debug and release mode. Set jsonxx::Settings::Assertions value to Disabled to disable assertions. Default value is Enabled. Usage The following snippets are from one of the unit tests. They are quite self-descriptive. using namespace std; using namespace jsonxx; string teststr( "{" " \"foo\" : 1," " \"bar\" : false," " \"person\" : {\"name\" : \"GWB\", \"age\" : 60,}," " \"data\": [\"abcd\", 42]," "}" ); // Parse string or stream Object o; assert(o.parse(teststr)); // Validation. Checking for JSON types and values as well assert(1 == o.get<Number>("foo")); assert(o.has<Boolean>("bar")); assert(o.has<Object>("person")); assert(o.get<Object>("person").has<Number>("age")); assert(!o.get<Object>("person").has<Boolean>("old")); assert(o.get<Object>("person").get<Boolean>("old", false)); assert(o.has<Array>("data")); assert(o.get<Array>("data").get<Number>(1) == 42); assert(o.get<Array>("data").get<String>(0) == "abcd"); assert(o.get<Array>("data").get<String>(2, "hello") == "hello"); assert(!o.has<Number>("data")); cout << o.json() << endl; // JSON output cout << o.xml(JSONx) << endl; // JSON to XML conversion (JSONx subtype) cout << o.xml(JXML) << endl; // JSON to XML conversion (JXML subtype) cout << o.xml(JXMLex) << endl; // JSON to XML conversion (JXMLex subtype) // Generate JSON document dynamically using namespace std; using namespace jsonxx; Array a; a << 123; a << "hello world"; a << 3.1415; a << 99.95f; a << 'h'; a << Object("key", "value"); Object o; o << "key1" << "value"; o << "key2" << 123; o << "key3" << a; cout << o.json() << endl; To do Custom JSON comments (C style /**/) when permissive parsing is enabled.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值