程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Poco::JSON::Array 中object 設置preserveInsertionOrder 時,stringify出錯-->深入解析,json.stringify

Poco::JSON::Array 中object 設置preserveInsertionOrder 時,stringify出錯-->深入解析,json.stringify

編輯:C++入門知識

Poco::JSON::Array 中object 設置preserveInsertionOrder 時,stringify出錯-->深入解析,json.stringify


 

在使用poco version 1.6.0時 Poco::JSON::Array 在object  設置preserveInsertionOrder =true 時

調用 array.stringify出錯.

 

在使用poco::json 輸出字符串

    std::string str1 = "\r";
    std::string str2 = "\n";
    Poco::JSON::Object obj1, obj2;
    obj1.set("payload", str1);
    obj2.set("payload", str2);
    std::ostringstream oss1, oss2;
    Poco::JSON::Stringifier::stringify(obj1, oss1);
    Poco::JSON::Stringifier::stringify(obj2, oss2);

    string srxxx=oss1.str()//正常輸出...

 

poco::json::array 輸出 字符串:

Object jObj2(true);
    
    std::string  strValue2="[{\"backspace1\":\"bs2222\",\"1backspace1\":\"1bs2222\"},{\"te1\":\"t1\",\"t2\":\"t2\"}]";
    jObj2.set("car", "這是中文[email protected]");
    jObj2.set("baz", "fas");

    std::stringstream ss2222;
    jObj2.stringify(ss2222);
    strxxx.clear();
    strxxx=CMyCodeConvert::Gb2312ToUtf8(ss2222.str());//gbk->utf8
    
    Object jObj3(true);

    jObj3.set("5", "2");
    jObj3.set("2", "2");

    Object jObj4(false);

    jObj4.set("51", "2");
    jObj4.set("21", "2");
    

        Poco::JSON::Array  array1;




        //array1.add(resultxxx);
        array1.add(jObj2);
        array1.add(jObj3);
        array1.add(jObj4);
        //jObj.set("arrar",array1);



        std::stringstream ssArray1;
        Stringifier::stringify(array1,ssArray1);
        //array1.stringify(ssArray1);
        std::string strArray1=ssArray1.str();//->>>>>>輸出字符串出錯.

 

but run time is error

 

追蹤代碼發現:

\JSON\src\Object.cpp:

 

Object(bool preserveInsertionOrder = false); //在map 中排序 ,輸出時按字母大小順序.
/// Default constructor. If preserveInsertionOrder, object
/// will preserve the items insertion order. Otherwise, items
/// will be sorted by keys.

preserveInsertionOrder = false 這個我比較反感,因為之前用jsoncpp 處理 某些東東時,因為輸出時入 輸入的json順序不 一致  走了不少彎路.

 

所以  preserveInsertionOrder = true  是我的愛 .

 

Stringifier::stringify(array1,ssArray1); 

 

 

----->

JSON\src\Stringifier.cpp:

 

else if ( any.type() == typeid(Array) )
{
const Array& a = any.extract<Array>();
a.stringify(out, indent == 0 ? 0 : indent, step);
}

 

--->

 

if ( any.type() == typeid(Object) )
{
const Object& o = any.extract<Object>();
o.stringify(out, indent == 0 ? 0 : indent, step);
}

 

--->

\JSON\src\Object.cpp:

void Object::stringify(std::ostream& out, unsigned int indent, int step) const
{
if (step < 0) step = indent;

if(!_preserveInsOrder)
doStringify(_values, out, indent, step);  // 不用代碼添加順序 ,則使用map窗口..jsoncpp也是map
else
doStringify(_keys, out, indent, step);//保留原有代碼添加順序, 則使用 std::deque<Dynamic::Var*> KeyPtrList
}

 

--->

 \Poco\JSON\Object.h

template <typename C>
void doStringify(const C& container, std::ostream& out, unsigned int indent, unsigned int step) const
{
 ....

 

Stringifier::stringify(getKey(it), out); //這兒   getKey(it), 出了問題
out << ((indent > 0) ? " : " : ":");

Stringifier::stringify(getValue(it), out, indent + step, step);

...

 

}

 

\JSON\src\Object.cpp:

const std::string& Object::getKey(KeyPtrList::const_iterator& iter) const
{
ValueMap::const_iterator it = _values.begin();
ValueMap::const_iterator end = _values.end();
for (; it != end; ++it)
{
if (it->second == **iter) return it->first;
}

throw NotFoundException((*iter)->convert<std::string>());  //----->這兒報錯
}

--->

 

Object.cpp中:


void Object::set(const std::string& key, const Dynamic::Var& value)
{
_values[key] = value;
if (_preserveInsOrder)
{
KeyPtrList::iterator it = _keys.begin();
KeyPtrList::iterator end = _keys.end();
for (; it != end; ++it)
{
if (key == **it) return;
}
_keys.push_back(&_values[key]);  //->這兒的內存地址發生了變化.
}
}

 

 

示例代碼中:

 

 array1.add(jObj2);  -->Object 轉到 (const Dynamic::Var& value)時

Foundation\include\Poco\Dynamic\Var.h:

Var(const T& val)
/// Creates the Var from the given value.
#ifdef POCO_NO_SOO
: _pHolder(new VarHolderImpl<T>(val))  --->>>發生了拷貝所以內存地址變化了.
{
}

 

後面在 https://github.com/pocoproject/poco/commit/3553a86d608321c1a06262c721aa766f1808cf2c 

作者說

const std::string& Object::getKey(KeyPtrList::const_iterator& iter) const 中

if (&it->second == *iter) return it->first;  

 

改成

if (it->second == **iter) return it->first;

注意 這個==是

 

poco開發版本地址:

https://github.com/pocoproject/poco/blob/develop/JSON/include/Poco/JSON/Object.h

https://github.com/pocoproject/poco/blob/develop/JSON/src/Object.cpp

 

以下只貼出了 重要更新的代碼.


//
// Object.h

如果是vs08的環境:

inline const Dynamic::Var& Object::getValue(KeyPtrList::const_iterator& it) const
{

return _values.at(**it);  //map.at 是C++ 11的標准,這兒不支持.

}

改成:

 

inline const Dynamic::Var& Object::getValue(KeyPtrList::const_iterator& it) const
{
const std::string & strKey=**it;
ValueMap ::const_iterator iter = _values.find(strKey);
if(iter!=_values.end())
return iter->second;

throw NotFoundException(strKey);
}

 
//
// Object.cpp
//
// $Id$
............

void Object::stringify(std::ostream& out, unsigned int indent, int step) const
{
    if (step < 0) step = indent;

    if(!_preserveInsOrder)
        doStringify(_values, out, indent, step);
    else
        doStringify(_keys, out, indent, step);
}


const std::string& Object::getKey(KeyPtrList::const_iterator& iter) const
{
    ValueMap::const_iterator it = _values.begin();
    ValueMap::const_iterator end = _values.end();
    for (; it != end; ++it)
    {
        if (it->first == **iter) return it->first;
    }

    throw NotFoundException(**iter);
}


void Object::set(const std::string& key, const Dynamic::Var& value)
{
    std::pair<ValueMap::iterator, bool> ret = _values.insert(ValueMap::value_type(key, value));
    if (_preserveInsOrder)
    {
        KeyPtrList::iterator it = _keys.begin();
        KeyPtrList::iterator end = _keys.end();
        for (; it != end; ++it)
        {
            if (key == **it) return;
        }
        _keys.push_back(&ret.first->first);
    }
}



 

測試結果:

Object jObj2(true);//-------->use preserveInsertionOrder=true

jObj2.set("car", "這是中文[email protected]");
jObj2.set("baz", "fas");
jObj2.set("baz1", "fas");
jObj2.set("1baz11", "fas");
Poco::JSON::Array array1;
array1.add(jObj2);

std::ostringstream oss122;
array1.stringify(oss122);
std::string fdsafsa=oss122.str();

std::cout<<"array1="<<fdsafsa<<std::endl;
//輸出:[{"car":"這是中文[email protected]","baz":"fas","baz1":"fas","1baz11":"fas"}]

 

   本以為到這兒就已經結束了....

 

  然而我錯了...

 

  上篇附筆中:

  poco json 中文字符,拋異常JSON Exception -->iconv 轉換 備忘錄。

  http://www.cnblogs.com/bleachli/p/4646092.html

  中的 suite()作下改變:

  

std::string  suite()
{


    std::string json = "";
        //"{"
        //"\"id\": 1123,"
        //"\"jsonrpc\": \" [email protected],大聖歸來.. \","
        //"\"total\": 2,"
        //"\"result\": "
        //"["
        //"{"
        //"\"id\": null,"
        //"\"picture\": \"http://placehold.it/32x32\","
        //"\"name\": \"這是中文測試.Crossman\","
        //"\"about\": \"《西游記之大聖歸來》是根據中國傳統神話故事進行拓展和演繹的3D動畫電影.xxxx Consectetuer suscipit volutpat eros dolor .\","
        //"\"friends\": "
        //"["
        //"{"
        //"},"
        //"{"
        //"\"id\": 2,"
        //"\"name\": \"Bailey Oldridge2\""
        //"},"
        //"{"
        //"\"id\": 3,"
        //"\"name\": \"Makayla Campbell3\""
        //"}"
        //"]"
        //"},"
        //"{"
        //"\"id\": 2,"
        //"\"picture\": \"http://placehold.it/32x32\","
        //"\"name\": \"2中名 歡迎 \","
        //"\"about\": \"2北京你好 dolor .\","
        //"\"friends\": "
        //"["
        //"]"
        //"}"
        //"]"
        //"}";


    std::string strUtf8=GetJsonSource(true);


    Parser parser;
    Var result;

    try
    {
        result = parser.parse(strUtf8);//json轉換...
    }
    catch(JSONException& jsone)
    {
        std::cout << jsone.message() << std::endl;
        return "result==NULL";
    }
    

    Object::Ptr object = result.extract<Object::Ptr>();
    int nObjectSize=object->size();

    //assert(object->size() > 0);
    DynamicStruct ds = *object;

    //遍歷...
    for(DynamicStruct::Iterator  itBegin=ds.begin();itBegin!=ds.end();itBegin++)
    {
        //std::string strvalue=itBegin;
        //Var var= itBegin->second;
        //std::cout<<"type:"<<var.type()<<std::endl;

        std::cout<<"K:"  << itBegin->first << " , value: " <<CMyCodeConvert::Utf8ToGb2312( itBegin->second.toString()) << std::endl;
    }

    std::cout<<std::endl<<std::endl<<std::endl;
    std::cout<<"+++++++++++++++++++++++++++++++++++++++++++++++++++"<<std::endl;


    json="";

    std::string strlation1xxxx;
    std::string strjstostring=strUtf8;
    std::string strTemp;
    std::string strKey;




    //std::string strKey="id";

    //key 是否存在
    strKey="id";
    if(object->has(strKey))
    {
        strTemp=CMyCodeConvert::Utf8ToGb2312( object->get(strKey).toString());
        std::cout<<"object->get("<<strKey<<")="<<strTemp<<std::endl;
    }

    strKey="id2232";
    if(object->has(strKey))
    {
        strTemp=CMyCodeConvert::Utf8ToGb2312( object->get(strKey).toString());

        std::cout<<"object->get("<<strKey<<")="<<strTemp<<std::endl;
    }

    strKey="jsonrpc";
    if(object->has(strKey))
    {
        strTemp=CMyCodeConvert::Utf8ToGb2312( object->get(strKey).toString());

        std::cout<<"object->get("<<strKey<<")="<<strTemp<<std::endl;

        std::string strxxx;
        
        std::cout<<"jsonrpc 編碼:"<<std::endl;
        std::string strxxxx=strTemp;
        for(int nxxx=0;nxxx<strxxxx.size();++nxxx)
        {
            unsigned char chTemp=strxxxx[nxxx];
            std::string strTemp=Poco::format("%hX",(unsigned short )chTemp);
            strTemp+=" ";
            //std::cout<<strTemp;
        }

        std::cout<<std::endl;

        //strjstostring+=strTemp;


        std::cout<<"object333->get("<<strKey<<")="<<strTemp<<std::endl;
    }

    strKey="total";
    if(object->has(strKey))
    {
        strTemp=CMyCodeConvert::Utf8ToGb2312( object->get(strKey).toString());

        std::cout<<"object->get("<<strKey<<")="<<strTemp<<std::endl;
    }


    strKey="result";
    if(object->has(strKey))
    {
        strTemp=CMyCodeConvert::Utf8ToGb2312( object->get(strKey).toString());

        std::cout<<"object->get("<<strKey<<")="<<strTemp<<std::endl;

            
        Var  vResult=object->get("result");

        Poco::JSON::Array::Ptr arrayResult = object->getArray("result");
        Poco::JSON::Array::Ptr arr22222 = vResult.extract<Poco::JSON::Array::Ptr>();

        Poco::Dynamic::Array dsarrayResult = *arrayResult;

        std::cout<<"arr22222->size()"<<arr22222->size()<<std::endl;
        std::cout<<"arrayResult->size()"<<arrayResult->size()<<std::endl;
        std::cout<<"arrayResult->size()"<<dsarrayResult.size()<<std::endl;


        for(int nIndex=0;nIndex<arrayResult->size();++nIndex)
        {
            Object::Ptr object = arrayResult->getObject(nIndex);


            strKey="id";
            if(object->has(strKey))
            {
                strTemp="";
                if(!object->get(strKey).isEmpty())
                {
                    strTemp=CMyCodeConvert::Utf8ToGb2312( object->get(strKey).toString());

                    std::cout<<"object->get("<<strKey<<")="<<strTemp<<std::endl;
                }

            }

            strKey="picture";
            if(object->has(strKey))
            {
                strTemp=CMyCodeConvert::Utf8ToGb2312( object->get(strKey).toString());

                std::cout<<"object->get("<<strKey<<")="<<strTemp<<std::endl;
            }

            strKey="name";
            if(object->has(strKey))
            {
                strTemp=CMyCodeConvert::Utf8ToGb2312( object->get(strKey).toString());

                std::cout<<"object->get("<<strKey<<")="<<strTemp<<std::endl;
            }

            strKey="about";
            if(object->has(strKey))
            {
                strTemp=CMyCodeConvert::Utf8ToGb2312( object->get(strKey).toString());

                std::cout<<"object->get("<<strKey<<")="<<strTemp<<std::endl;
            }

            strKey="friends";
            if(object->has(strKey))
            {
                strTemp=object->get(strKey).toString();

                std::cout<<"object->get("<<strKey<<")="<<strTemp<<std::endl;

                Poco::JSON::Array::Ptr arrayFriends = object->getArray(strKey);
                for(int nIndex=0;nIndex<arrayFriends->size();++nIndex)
                {
                    Object::Ptr objectFriends = arrayFriends->getObject(nIndex);
                    DynamicStruct dsTemp = *objectFriends;

                    for(DynamicStruct::Iterator  itBegin=dsTemp.begin();itBegin!=dsTemp.end();itBegin++)
                    {
                        std::cout<<"K:"  << itBegin->first << " , value: " << CMyCodeConvert::Utf8ToGb2312(itBegin->second.toString() )<< std::endl;
                    }

                }
            }



            std::cout<<std::endl<<std::endl<<std::endl;
            std::cout<<"+++++++++++++++++++++++++++++++++++++++++++++++++++"<<std::endl;

            std::cout<<std::endl<<std::endl<<std::endl;

        }




    }

    return strjstostring;
}

GetJsonSource()代碼:

std::string GetJsonSource(bool bUtf8)
{
    bool bIspreserveInsertionOrder=true;
    
    Object jObjRoot(bIspreserveInsertionOrder);//-------->use preserveInsertionOrder=true
    
    jObjRoot.set("id", 1123);
    jObjRoot.set("car",  ("這是中文[email protected],[email protected],大聖歸來..") );
    jObjRoot.set("total", 2);

    Poco::JSON::Array arrayResult;
    
    for(int nIndex=0;nIndex<2;nIndex++)
    {
        Object jArrayObj(bIspreserveInsertionOrder);
        jArrayObj.set("id", nIndex);
        jArrayObj.set("picture",("http://placehold.it/111.abc.") );
        jArrayObj.set("name",("這是中文測試.Crossman.") );
        jArrayObj.set("about",("《西游記之大聖歸來》是根據中國傳統神話故事進行拓展和演繹的3D動畫電影.xxxx Consectetuer suscipit volutpat eros dolor .") );

        Poco::JSON::Array arrayFriends;
        for(int i=0;i<5;++i)
        {
            Object jarrayFriendsObj(bIspreserveInsertionOrder);
            jarrayFriendsObj.set("id", i);
            jarrayFriendsObj.set("name", (Poco::format("name%d,這是無可奈何花落去!",i)));

            arrayFriends.add(jarrayFriendsObj);
        }


        jArrayObj.set("friends",arrayFriends);

        arrayResult.add(jArrayObj);

    }

    jObjRoot.set("result",arrayResult);
    
    std::string strObjRoot;
    std::ostringstream ojObjRoot;
    //
    //bIspreserveInsertionOrder =false時程序正常運行.
    //bIspreserveInsertionOrder =true 時程序出錯
    //Poco\JSON\Object.cpp 
    //const std::string& Object::getKey(KeyPtrList::const_iterator& iter) const
    //iter is null.
    //產生memcpy 錯誤..
    //
    jObjRoot.stringify(ojObjRoot);//

    strObjRoot=ojObjRoot.str();
    
    if(bUtf8)
        strObjRoot=CMyCodeConvert::Gb2312ToUtf8(strObjRoot);
    
    //std::string strGbkTemp=CMyCodeConvert::Utf8ToGb2312(strObjRoot);
    return strObjRoot;

}

原因是

typedef std::deque<const std::string*> KeyPtrList; 這兒是指針地址,臨時變量內容已經over了.

so...再改改代碼:

 

poco\JSON\include\Poco\JSON\Object.h 改動部分

typedef std::deque< std::string> KeyPtrList;

inline const Dynamic::Var& Object::getValue(KeyPtrList::const_iterator& it) const
{
const std::string & strKey=*it;
ValueMap ::const_iterator iter = _values.find(strKey);
if(iter!=_values.end())
return iter->second;

throw NotFoundException(strKey);
}

 

 

 

poco\JSON\src\Object.cpp 中改動部分:

const std::string& Object::getKey(KeyPtrList::const_iterator& iter) const
{
ValueMap::const_iterator it = _values.begin();
ValueMap::const_iterator end = _values.end();
for (; it != end; ++it)
{
if (it->first == *iter) return it->first;
}

throw NotFoundException(*iter);
}


void Object::set(const std::string& key, const Dynamic::Var& value)
{
std::pair<ValueMap::iterator, bool> ret = _values.insert(ValueMap::value_type(key, value));
if (_preserveInsOrder)
{
KeyPtrList::iterator it = _keys.begin();
KeyPtrList::iterator end = _keys.end();
for (; it != end; ++it)
{
if (key == *it) return;
}
_keys.push_back(ret.first->first);
}
}

   

  GetJsonSource()輸出的結果可在 http://www.bejson.com/  中校驗.

  -_- 終於成功了...

  

  把代碼在debian下編譯看下 通過http訪問結果:

  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved