以前在cocos2d-x项目中用到json解析,集成了libjson库后发现网上提供的解析方法大多是在解析过程中取得值,并没有将解析结果有效的保存起来,于是摸索一番,把解析结果根据数据格式存到数组或字典当中。
不敢独享,代码奉上:
using namespace std; void JsonUtil:: parseArrJSON(JSONNODE *n,CCObject **obj) { if (n == NULL) { CCLOG("Invalid JSON Node\n"); return; } bool isAry=false; // Parser JSONNODE_ITERATOR it = json_begin(n); char *key=json_name(*it); if (strcmp(key, "")==0) { //是数组 *obj=CCArray::create(); isAry=true; }else{ //是字典 *obj=CCDictionary::create(); isAry=false; } while (it != json_end(n)) { if (*it == NULL) { CCLOG("Invalid JSON Node\n"); return; }else if(json_type(*it)==JSON_NULL){ CCString *char_str=CCString::ccs(""); if (isAry) { ((CCArray *)*obj)->addObject(char_str); }else{ string key=json_name(*it); CC_ASSERT(!key.empty()); ((CCDictionary *)*obj)->setObject(char_str, key); } }else if (json_type(*it) == JSON_ARRAY || json_type(*it) == JSON_NODE) { CCObject *tempobj=NULL; parseArrJSON(*it,&tempobj); if (isAry) { ((CCArray *)*obj)->addObject(tempobj); }else{ string key=json_name(*it); CC_ASSERT(!key.empty()); ((CCDictionary *)*obj)->setObject(tempobj, key); } } else if(json_type(*it)==JSON_STRING){ json_char *value = json_as_string(*it); CCString *char_str=CCString::create(value); if (isAry) { ((CCArray *)*obj)->addObject(char_str); }else{ string key=json_name(*it); CC_ASSERT(!key.empty()); ((CCDictionary *)*obj)->setObject(char_str, key); } json_free(value); }else if(json_type(*it)==JSON_NUMBER){ // json_int_t value = json_as_int(*it); json_number value = json_as_float(*it); CCString *char_str=CCString::createWithFormat("%.2f",value); if (isAry) { ((CCArray *)*obj)->addObject(char_str); }else{ string key=json_name(*it); CC_ASSERT(!key.empty()); ((CCDictionary *)*obj)->setObject(char_str, key); } } ++it; } } CCObject * JsonUtil:: jsonValue(const char *_char){ JSONNODE *an = json_parse(_char); CCObject *obj=NULL; JsonUtil::parseArrJSON(an,&obj); json_delete(an); return obj; }
创建个类JsonUtil,包含两个静态方法,使用的时候调用JsonUtil::jsonValue(const char *_char),解析的结果会保存在字典或者数组中,例子:
const char *betem="[{\"中国食谱\":[\"上海醉蟹\",\"北京锅烧鸡\",\"川式凉拌豇豆\",\"清真酱牛肉\"],\"国外食谱\":[\"泰式柠檬肉片\",\"鸡柳汉堡\",\"蒸桂鱼卷 \"],\"更多\":{\"中式\":[\"南\",\"北\",{\"地方\":[\"小吃\",\"大餐\"]},\"更多选择\"]}},{\"菜谱分类\":[\"上海菜\",\"贵州菜\",\"潮汕菜\",\"云南菜\",\"东北菜\",\"安徽菜\",\"广东菜\",\"浙江菜\",\"湖南菜\"]},\"其它\"]";
CCArray *ary= (CCArray *) JsonUtil::jsonValue(betem);
ccout(ary);
这里的ccout是自定义的用来打印数组和字典的方法。cocos2d-x的CCLog跟NSLog相比起来真是差远了,哪怕把时间打印出来也好啊。
附上ccout代码,可以用来打印保存在CCArray或CCDictionary中的json数据,勉强做成类似NSLog输出的样子:
void ccout(CCObject *thob,int donotset=0,bool dot=false); void AppDelegate::ccout(CCObject *thob,int donotset,bool dot){ if (dynamic_cast<CCDictionary *>(thob)) { cout<<"{"; CCDictionary *temp=(CCDictionary *)thob; CCDictElement *ele; CCDICT_FOREACH(temp, ele){ const char *key=ele->getStrKey(); CCObject *ob=ele->getObject(); cout<<endl; for (int i=0; i<donotset+1; i++)cout<<"\t"; cout<<key<<"="; this->ccout(ob,donotset+2); cout<<";"; } cout<<std::endl; for (int i=0; i<donotset; i++)cout<<"\t"; cout<<"}"; if (dot) { cout<<","; } }else if (dynamic_cast<CCArray *>(thob)){ cout<<"("; CCArray *temp=(CCArray *)thob; CCObject *ob; CCARRAY_FOREACH(temp, ob){ if (dynamic_cast<CCDictionary *>(ob)) { if (ob!=temp->lastObject()) { this->ccout(ob,donotset+1,true); }else{ this->ccout(ob,donotset+1); } }else if (dynamic_cast<CCArray *>(ob)) { this->ccout(ob,donotset+1); }else if (dynamic_cast<CCString *>(ob)) { cout<<((CCString*)ob)->getCString(); if (ob!=temp->lastObject()) { cout<<","; } }else{ cout<<"undefined class cout"; } } cout<<")"; } }
输出结果:
({ 中国食谱=(上海醉蟹,北京锅烧鸡,川式凉拌豇豆,清真酱牛肉); 国外食谱=(泰式柠檬肉片,鸡柳汉堡,蒸桂鱼卷 ); 更多={ 中式=(南,北,{ 地方=(小吃,大餐); },更多选择); }; },{ 菜谱分类=(上海菜,贵州菜,潮汕菜,云南菜,东北菜,安徽菜,广东菜,浙江菜,湖南菜); },其它)