CCObjectからJSONを作成する

#CCObjectからJSONを作成します（cocos2d-x ver2.2.1）

前回はJSONをパースする方法を投稿したので、今回はその逆でCCObjectからJSONを作成する方法を投稿します。

折角cocos2d-xを利用しているのだからCCObjectからJSONを作れたら良いなと思い検索していたら、下記の記事を見つけました。
[CCObjectの情報を出力する](http://qiita.com/e73ryo/items/347975cffede21f7a7a3)

上記の記事を参考に、すぐにCCLogで出力するのではなくstreamに溜め込んで返すような感じにしています。
対応しているのはCCString、CCInteger、CCFloat、CCBool、CCArray、CCDictionaryに対応しており、入れ子構造にも対応している設計になっています。
尚、出力されたJSONをCCLogで表示すると中身がちゃんと入っているか確認出来るので、CCObjectの簡易オブジェクトビューアとしても利用出来ると思います。

```cpp
#define OutputCCObject( obj )   ( outputObject( obj , "") )

const char* outputObject(CCObject* obj, const char* key);

inline const char* outputArray(CCArray* array)
{
    std::ostringstream stream;
    stream << "[";
    
    for(int i = 0 ; i < array->count(); ++i)
    {
        CCObject* value = array->objectAtIndex(i);
        
        stream << outputObject(value, "");
        
        if(i != array->count() - 1) {
            stream << ",";
        }
    }
    
    stream << "]";
    return stream.str().c_str();
}

inline const char* outputDictionary(CCDictionary* dictionary)
{
    std::ostringstream stream;
    stream << "{";
    
    CCArray* allKeys = dictionaryAllKeys(dictionary);
    CCObject* obj;
    int i = 0;
    CCARRAY_FOREACH(allKeys, obj)
    {
        CCString* key = (CCString*)obj;
        
        CCObject* value = dictionary->objectForKey(key->getCString());
        
        stream << outputObject(value, key->getCString());
        
        if(i++ != allKeys->count() - 1) {
            stream << ",";
        }
    }

    delete allKeys;
    
    stream << "}";
    return stream.str().c_str();
}

inline const char* outputObject(CCObject* obj, const char* key)
{
    std::ostringstream stream;
    std::ostringstream initialStream;
    
    if(strlen(key) != 0)
    {
        initialStream << "\"" << key << "\":";
    }
    
    if(typeid(*obj) == typeid(CCString))
    {
        stream << initialStream.str() << "\"" << ((CCString*)obj)->getCString() << "\"";
    }
    else if(typeid(*obj) == typeid(CCInteger))
    {
        stream << initialStream.str() << ((CCInteger*)obj)->getValue();
    }
    else if(typeid(*obj) == typeid(CCFloat))
    {
        stream << initialStream.str() << ((CCFloat*)obj)->getValue();
    }
    else if(typeid(*obj) == typeid(CCBool))
    {
        if( ((CCBool*)obj)->getValue())
        {
            stream << initialStream.str() << "true";
        } else {
            stream << initialStream.str() << "false";
        }
    }
    else if(typeid(*obj) == typeid(CCArray))
    {
        stream << initialStream.str() << outputArray((CCArray*)obj);
    }
    else if(typeid(*obj) == typeid(CCDictionary))
    {
        stream << initialStream.str() << outputDictionary((CCDictionary*)obj);
    }
    else
    {
        stream << initialStream.str() << typeid(obj).name();
    }
    
    return stream.str().c_str();
}
```

OutputCCObject( obj ) は const char* を返しますので、ケースによってはstring等に保存したりして下さい。
下記の例ではCCLogに出力しているので、そのまま使用しています。
※CCObjectのcreateを使用する際はメモリ管理に気をつけて下さい。

例) これはあくまでも例ですので、実際にCCArrayやCCDictionaryで使う場合はretainを適切にするか、newで作成して下さい。

```cpp
    CCEGLView* view = CCDirector::sharedDirector()->getOpenGLView();
    CCSize frameSize = view->getFrameSize();
    
    CCDictionary* paramDic = CCDictionary::create();
    paramDic->setObject(CCString::create("ABCD"), "uuid");
    paramDic->setObject(CCFloat::create(1.1), "version");
    
    CCArray* mainArray = CCArray::create();
    mainArray->addObject(CCBool::create(false));
    mainArray->addObject(CCString::create("dummy"));
    
    CCDictionary* arrayDic = CCDictionary::create();
    CCArray* subArray = CCArray::create(CCInteger::create(4), CCString::create("test"));

    arrayDic->setObject(subArray, "subarray");
    mainArray->addObject(arrayDic);
    paramDic->setObject(mainArray, "mainarray");
    
    CCDictionary* sizeDic = new CCDictionary();
    sizeDic->setObject(CCFloat::create(frameSize.width), "width");
    sizeDic->setObject(CCFloat::create(frameSize.height), "height");
    sizeDic->setObject(CCBool::create(true), "ios");
    paramDic->setObject(sizeDic, "screen");
    
    CCLog("OutputCCObject = %s", OutputCCObject(paramDic));
```

結果)

```cpp
OutputCCObject = {"uuid":"ABCD","version":1.1,"mainarray":[false,"dummy",{"subarray":[4,"test",PN7cocos2d8CCObjectE]}],"screen":{"width":640,"height":1136,"ios":true}}
```

今回は std::ostringstream を使いましたが、他にももっと良い方法があるかと思います。
もし良いアイディアがあったら教えて下さい。

よろしくお願いします。