9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CCObjectからJSONを作成する

Last updated at Posted at 2013-12-10

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

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

折角cocos2d-xを利用しているのだからCCObjectからJSONを作れたら良いなと思い検索していたら、下記の記事を見つけました。
CCObjectの情報を出力する

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

#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で作成して下さい。

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

結果)

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

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

よろしくお願いします。

9
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?