LoginSignup
9

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 を使いましたが、他にももっと良い方法があるかと思います。
もし良いアイディアがあったら教えて下さい。

よろしくお願いします。

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
What you can do with signing up
9