Json在ajax領(lǐng)域很流行,記得當(dāng)時看過它的介紹后很興奮,網(wǎng)上找了一些解析json的c
和c++代碼,不過沒有找到特別好的,有的寫得不錯不過要依賴于boost,有的用c寫的不大好用,好在json語法簡單,參考了一些c/c++的json解析代碼做了一個json類,最近又把去年寫的json類修改為unicode下使用,增了一些功能,現(xiàn)在CJsonw可以解析const char *型輸入,也可解析const wchar_t *型輸入,可解析ansi編碼、unicode編碼、utf8編碼的json文件。看看我的CJsonw定義:
JsonwType type; //Json類型, true false null直接由類型表示了
DWORD tag; //tag,用戶自用值,默認(rèn)為0
union
{
struct{
wchar_t *cstring;//字符串型值
int clen; //cstring按照字符計(jì)算的分配個數(shù),包括可能的0
};
double dvalue; //double值
struct
{
int ivalue; //int值
DWORD dwhigh; //高部
};
__int64 i64value; //int64值
OBJS *objs; //對象型值
ARRAYS *arrays; //數(shù)組型值
};
Sizeof(CJsonw) == 16
OBJS類型描述無序的key-value型數(shù)據(jù),ARRAYS描述 array型有序數(shù)據(jù),定義如下:
typedef CHashiW<CJsonw *, CJsonw *> OBJS;
typedef std::vector<CJsonw *> ARRAYS;
支持以下構(gòu)造函數(shù):
CJsonw(JsonwType t=json_null);
CJsonw(int value);
CJsonw(__int64 value);
CJsonw(float value);
CJsonw(double value);
CJsonw(const wchar_t *value);
//數(shù)組型構(gòu)造函數(shù)
CJsonw(int *numbers, int count);
CJsonw(__int64 *numbers, int count);
CJsonw(float *numbers, int count);
CJsonw(double *numbers, int count);
CJsonw(const wchar_t **strings, int count);
支持以下賦值函數(shù):
bool setnull();
bool set(bool value);
bool set(int value);
bool set(__int64 value);
bool set(float value);
bool set(double value);
bool set(const wchar_t *value);
bool set(int *numbers, int count);
bool set(__int64 *numbers, int count);
bool set(float *numbers, int count);
bool set(double *numbers, int count);
bool set(const wchar_t **strings, int count);
//修改常規(guī)值,就是true, false, int, real, string
bool setbystring(const wchar_t *value);
支持以下輸入:
bool parse(const char *string);
bool parse(const wchar_t *string);
bool parsefile(FILE *fp);
bool parsefile(LPCTSTR filename);
文件可以ansi編碼、unicode編碼、或者utf8編碼
支持以下wchar_t型輸出:
//dump,默認(rèn)為unicode編碼
//uunicode表示字符串中的unicode字符是否按照\uxxxx格式輸出
//bDisp為true按照友好格式顯示,會輸出\t換行等方便閱讀
//bDisp為false按照緊湊模式顯示,沒有多余字符,方便網(wǎng)絡(luò)傳輸?shù)葓龊?/span>
bool dump(CBlockBuffer *pbk, bool bNameQuotes=true, bool uunicode=false, bool bDisp=true);
//跟上面的dump一樣,但如果成功會在buf里面插入一個'\0'字符
bool dump0(CBlockBuffer *pbk, bool bNameQuotes=true, bool uunicode=false, bool bDisp=true);
bool save(LPCTSTR filename);
bool save(FILE *fp);
保存到文件默認(rèn)為UNICODE格式
支持以下ANSI型輸出:
//a系列dump為ansi編碼輸出
//bDisp為true按照友好格式顯示,會輸出\t換行等方便閱讀
//bDisp為false按照緊湊模式顯示,沒有多余字符,方便網(wǎng)絡(luò)傳輸?shù)葓龊?/span>
bool dumpa(CBlockBuffer *pbk, bool bNameQuotes=true, bool uunicode=true, bool bDisp=true);
//跟上面的dump一樣,但如果成功會在buf里面插入一個'\0'字符
bool dumpa0(CBlockBuffer *pbk, bool bNameQuotes=true, bool uunicode=true, bool bDisp=true);
ANSI型輸出主要用在節(jié)省網(wǎng)絡(luò)帶寬或者和其他系統(tǒng)交換數(shù)據(jù)的情況下。
支持以下類型判別函數(shù):
//類型判別函數(shù)
bool IsArray() const { return type==json_array; }
bool IsObject() const { return type==json_object; }
bool IsInt() const { return type==json_int; }
bool IsReal() const { return type==json_real; }
bool IsNumber() const { return IsInt()||IsReal(); }
bool IsNull() const { return type==json_null; }
bool IsTrue() const { return type==json_true; }
bool IsFalse() const { return type==json_false; }
bool IsString() const { return type==json_string; }
支持以下一些直接取值函數(shù):
const wchar_t *getordef(const wchar_t *strdef)
int getordef(int idef)
__int64 getordef(__int64 idef)
double getordef(double ddef)
bool getordef(bool bdef)
//取array的元素
CJsonw *get(int n)
CJsonw *operator[](int n) const
//取obj的元素
CJsonw *get(const wchar_t *name)
CJsonw *operator[](const wchar_t *name) const
支持以下取array型子元素?cái)?shù)據(jù)的函數(shù):
const wchar_t *getordef(int n, const wchar_t *strdef)
int getordef(int n, int idef)
__int64 getordef(int n, __int64 idef)
double getordef(int n, double ddef)
bool getordef(int n, bool bdef)
支持以下取obj型子元素?cái)?shù)據(jù)的函數(shù):
const wchar_t *getordef(const wchar_t *name, const wchar_t *strdef)
int getordef(const wchar_t *name, int idef)
__int64 getordef(const wchar_t *name, __int64 idef)
double getordef(const wchar_t *name, double ddef)
bool getordef(const wchar_t *name, bool bdef)
支持以下obj遍歷函數(shù):
//遍歷函數(shù),最常見寫法:
//for(CJsonw::OBJIT *p=xxx.FirstObj(); p; p=p->next())...
OBJIT *firstobj()
//求array或object元素個數(shù),string類型返回分配的字符個數(shù)(包括可能的),其他類型都返回
int size() const
另外支持一些增加array子元素函數(shù):
bool add(CJsonw *pnode)
bool del(int n, bool bfree=true)
bool addnull(){ return add(new CJsonw(json_null)); }
bool addtrue(){ return add(new CJsonw(json_true)); }
bool addfalse(){ return add(new CJsonw(json_false)); }
bool add(int value){ return add(new CJsonw(value)); }
bool add(__int64 value){ return add(new CJsonw(value)); }
bool add(float value){ return add(new CJsonw(value)); }
bool add(double value){ return add(new CJsonw(value)); }
bool add(const wchar_t *value){ return add(new CJsonw(value)); }
也支持obj增加刪除子對象函數(shù):
bool addobj(const wchar_t *name, CJsonw *pnode)
bool delobj(const wchar_t *name, bool bfree=true)
bool addobjnull(const wchar_t *name){ return addobj(name, new CJsonw(json_null)); }
bool addobjtrue(const wchar_t *name){ return addobj(name, new CJsonw(json_true)); }
bool addobjfalse(const wchar_t *name){ return addobj(name, new CJsonw(json_false)); }
bool addobj(const wchar_t *name, int value){ return addobj(name, new CJsonw(value)); }
bool addobj(const wchar_t *name, __int64 value){ return addobj(name, new CJsonw(value)); }
bool addobj(const wchar_t *name, float value){ return addobj(name, new CJsonw(value)); }
bool addobj(const wchar_t *name, double value){ return addobj(name, new CJsonw(value)); }
bool addobj(const wchar_t *name, const wchar_t *value){ return addobj(name, new CJsonw(value)); }
還有一些特殊函數(shù):
//計(jì)算整個樹的crc
DWORD calccrc();
//計(jì)算整個樹的md5,要求md5不少于個字節(jié)
byte *calcmd5(byte *md5);
//計(jì)算hex表示的md5,不寫尾部,要求md5hex不少于個字符
char *calcmd5hex(char *md5hex, const byte x='x');
//計(jì)算hex表示的md5,寫尾部,要求md5hex不少于個字符
char *calcmd5hex0(char *md5hex, const byte x='x');
在json類上花了較多時間,主要是覺得這個類很有用,可以描述任意對象,易保存易傳輸易構(gòu)造,對速度要求不苛刻的應(yīng)用程序用json作為基本數(shù)據(jù)結(jié)構(gòu)很合適,配合json里面的data自定義字段理論上支持描述任意對象,配合使用一些cache可擴(kuò)大json類的使用范圍,用它取代ini xml等配置簡直是大材小用,用json類來做stringtable簡直就是小菜一碟,而且還是hash級高效率,絲毫不比手工做一個hash_map<,>表差。
在實(shí)際應(yīng)用中,去年有一個網(wǎng)絡(luò)驗(yàn)證的項(xiàng)目就大量使用了這個類,配置、幫助都是json格式,應(yīng)用中管理大量對象的內(nèi)存數(shù)據(jù)庫也是用了json類,編碼后直接網(wǎng)上傳輸,server內(nèi)部也是一個json對象直接管理了大量用戶的信息,非常方便,可以說用json類使得這個程序少寫了大量代碼,也使得整個項(xiàng)目只用了1個月時間就做出來了,還部署成master – master- slave(N)模式穩(wěn)定運(yùn)行了將近1年時間。
在另一些網(wǎng)絡(luò)應(yīng)用中,俺將json格式數(shù)據(jù)作為變長包使用,前面俺寫過一篇短文介紹了變長包最常見的幾種格式,分別是:
1、 key\0value\0…
2、 json格式
3、 xml格式
使用json格式作為變長包現(xiàn)在很流行,這也是大量ajax所采用所依賴的技術(shù),qq種菜,google搜索預(yù)列表都是采用json格式的。