Cocos2d-xでJSONをCCDictionaryに変換する

cocos2d-x 2.1.3からspineというAnimationのToolがSupportされて、それにJSONをパースするコードが含まれているため、外部からpicojsonなどのライブラリを持ってこなくてもJSONをparse出来るようになりました。

spineについてはよくわからないので、↓これを見てください。
Spine: 2D skeletal animation for games

parse出来るようになったけど、spine/Json.hの使い方が探してもろくに出てこないのでまとめます。spineでググって出てくるのがアニメーションツールだったので、違うspineじゃねぇか!って思って見てないのですが、公式のドキュメント漁れば使い方乗ってたのかもしれません。

長い文章を読むのが苦手な人は、このgistを見ればOKです。

https://gist.github.com/gin0606/7939165

Jsonのparse

Json文字列をJsonオブジェクト(構造体)にするのは下記の1行で出来ます。

Json_create(jsonString);

この時渡すJSONのFormatが間違っているとparseしてくれないので気をつけましょう。

値の取り出し

Json *はtypeという属性を持っていて、それを元に値を取り出します。

CCObject *JsonUtil::parseValue(Json *pJsonValue) {
    if (!pJsonValue) {return NULL;}
    CCObject *object = NULL;
    switch (pJsonValue->type) {
        case Json_False:
            object = CCBool::create(false);
            break;
        case Json_True:
            object = CCBool::create(true);
            break;
        case Json_NULL:
            object = NULL;
            break;
        case Json_Number:
            object = CCFloat::create(pJsonValue->valuefloat);
            break;
        case Json_String:
            if (pJsonValue->valuestring) {
                object = CCString::create(pJsonValue->valuestring);
            }
            break;
        case Json_Array:
            object = parseArray(pJsonValue);
            break;
        case Json_Object:
            object = parseObject(pJsonValue->child);
            break;
        default:
            object = NULL;
            break;
    }
    return object;
}

Json_False, Json_True, Json_NULLは、Json *が値を持っておらず、typeを元にvalueを判断する形になります。

Json_Number, Json_Stringについては、->valuefloat, pJsonValue->valuestringで取り出します。

Json_Array, Json_Objectについては、更に深く入って値を取り出します。

Json_Arrayの場合

CCArray *JsonUtil::parseArray(Json *pJson) {
    int arrayLength = Json_getSize(pJson);
    CCArray *array = CCArray::create();
    for (int i = 0; i < arrayLength; i++) {
        Json *item = Json_getItemAt(pJson, i);
        CCObject *object = parseValue(item);
        if (object) {
            array->addObject(object);
        }
    }
    return array;
}

Json_getSize(pJson)でArrayの長さが取れるので、それを元にfor文を作ってJson_getItemAt(pJson, index);で値を取り出します。

取り出した値は、先ほど宣言したparseValueに渡して値を取り出します。

Json_Objectの場合

CCObject *JsonUtil::parseObject(Json *pJson) {
    CCDictionary *root = CCDictionary::create();
    for (Json *item = pJson; item; item = item->next) {
        CCObject *value = parseValue(item);
        if (value) {
            root->setObject(value, item->name);
        }
    }
    return root;
}

Json_Objectは、双方向リストになっているので、->nextを使って値を取り出していきます。

値はparseValueで取り出します。


以上を読めば、spine/Json.hから任意の値を取り出せると思います。

僕はJson_getStringとかJson_getIntで値を取り出すのかと思って大分ハマりました。

ついでにJson文字列をCCDictionaryに変換するコードを書いたので貼っておきます。まだ実用してないし、テストコードもないので、まともな状態にしてrepository作りたいと思ってます。

Cocos2d-xでJSONをCCDictionary/CCArrayに変換する

2013/12/15追記

リポジトリは作った。 https://github.com/gin0606/cocos2d-x-extention-CCJson