Help us understand the problem. What is going on with this article?

CCObjectからJSONを作成する

More than 5 years have passed since last update.

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

よろしくお願いします。

tyama83
家庭用ゲーム(スーパーファミコンから)のプログラマとしてゲーム業界に入り、途中組み込み系やWeb系などのSEやエンジニア、PM、PL等の様々なキャリアを積みながら、近年ではネットワークゲームやソーシャルゲーム、スマホ向けネイティブアプリやサイトなどの開発を行っています。 ネットワークとスマホに関連した事業でお役に立てる事があれば、是非お願いいたします!
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした