Skip to content
isdnetworks
Go back

한쪽은 층이 있고 한쪽은 평평했다

서버에서 받은 아이템 정보를 게임에 넣는데 코드가 자꾸 길어졌다. JsonCpp 로 읽어 ShopItem 에 옮기는 부분이다.

Table of contents

Open Table of contents

두 구조가 달랐다

서버가 주는 JSON 은 층이 있었고 ShopItem 은 평평했다. 한 값을 꺼내는 데 네 단계를 지나야 했다.

item.typeCode = codeOf(root["items"][i]["info"]["type"]["code"].asCString());

중간에 하나라도 없으면 asCString() 에서 죽는다. 그래서 꺼내기 전에 isMember 를 넣었다. 확인할 자리가 층마다 있어서 코드가 더 길어졌다.

확인을 한 자리에 모았다

경로를 점으로 이어 받는 pick 을 하나 뒀다.

static std::string pick(const Json::Value& v, const char* path, const char* def = "") {
    std::vector<std::string> keys = split(path, '.');
    Json::Value cur = v;
    for (size_t i = 0; i < keys.size(); ++i) {
        if (!cur.isMember(keys[i])) {
            CCLOG("json: no path %s", path);
            return def;
        }
        cur = cur[keys[i]];
    }
    return cur.asString();
}

std::stringstd::vector 를 쓰려면 Application.mkAPP_STL := gnustl_static 이 있어야 한다. NDK 의 기본 런타임에는 STL 이 거의 없다.

부르는 쪽이 한 줄이 됐고 중간에 없어도 안 죽는다. 다만 조용히 기본값이 들어가는 것은 그것대로 문제다. 없는 경로를 만나면 CCLOG 에 남기게 했다. 개발 중에 서버 구조가 바뀌면 logcat 으로 바로 보인다.

어느 쪽에 맞출지 정했다

변환을 편하게 하는 것과 구조를 맞추는 것은 다른 이야기였다. 서버 JSON 에 맞추면 변환이 없어진다. 대신 게임 코드가 매번 Json::Value 를 따라가야 한다. ShopItem 에 맞추려면 서버 쪽에 변경을 요청해야 한다.

서버는 다른 곳에서도 쓰고 있어 못 바꾼다. 게임 안에서 Json::Value 를 들고 다니는 것도 느리다. 그래서 가운데에 옮기는 자리를 하나 뒀다. JSON 구조가 바뀌어도 거기만 고친다.

필수와 선택, 그리고 받은 것

pick 이 전부 기본값을 주면 이름 없는 아이템이 생긴다. 없으면 버릴 것과 기본값으로 둘 것을 나눴다.

out.id = node.get("id", 0).asInt();
if (out.id == 0) return false;                    // 없으면 버린다
out.typeCode = codeOf(pick(node, "info.type.code", "ETC").c_str());  // 없어도 된다

이름을 복사하는 부분도 고쳤다. char name[32] 인데 서버가 그보다 긴 이름을 주면 넘친다. strcpysnprintf 로 바꿨다. 잘리기는 해도 끝에 \0 이 들어가고 넘치지 않는다. 보내는 쪽이 지켜 줄 것이라고 보면 안 된다.

받은 것을 개발 빌드에서 그대로 찍는 것도 넣었다. Json::StyledWriter 로 원문을 남긴다. 옮기고 나면 원래 받은 것이 사라져서 값이 이상할 때 무엇을 받았는지 볼 수가 없었다.

내가 잘못 옮긴 것인지 받은 것이 원래 그런지가 이걸로 갈렸다. 이 구분이 없으면 서버 쪽에 문의할지 내 코드를 볼지부터 정하지 못한다.

정리


Share this post on:

Previous Post
빌드가 20분 걸렸다
Next Post
단계마다 자료 형태가 바뀌고 있었다