Json在ajax领域很流行,记得当时看过它的介绍后很兴奋,网上找了一些解析json的c
和c++代码,不过没有找到特别好的,有的写得不错不过要依赖于boost,有的用c写的不大好用,好在json语法简单,参考了一些c/c++的json解析代码做了一个json类,最近又把去年写的json类修改为unicode下使用,增了一些功能,现在CJsonw可以解析const char *型输入,也可解析const wchar_t *型输入,可解析ansi编码、unicode编码、utf8编码的json文件。看看我的CJsonw定义:
JsonwType type; //Json类型, true false null直接由类型表示了
DWORD tag; //tag,用户自用值,默认为0
union
{
struct{
wchar_t *cstring;//字符串型值
int clen; //cstring按照字符计算的分配个数,包括可能的0
};
double dvalue; //double值
struct
{
int ivalue; //int值
DWORD dwhigh; //高部
};
__int64 i64value; //int64值
OBJS *objs; //对象型值
ARRAYS *arrays; //数组型值
};
Sizeof(CJsonw) == 16
OBJS类型描述无序的key-value型数据,ARRAYS描述 array型有序数据,定义如下:
typedef CHashiW<CJsonw *, CJsonw *> OBJS;
typedef std::vector<CJsonw *> ARRAYS;
支持以下构造函数:
CJsonw(JsonwType t=json_null);
CJsonw(int value);
CJsonw(__int64 value);
CJsonw(float value);
CJsonw(double value);
CJsonw(const wchar_t *value);
//数组型构造函数
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);
支持以下赋值函数:
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);
//修改常规值,就是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,默认为unicode编码
//uunicode表示字符串中的unicode字符是否按照\uxxxx格式输出
//bDisp为true按照友好格式显示,会输出\t换行等方便阅读
//bDisp为false按照紧凑模式显示,没有多余字符,方便网络传输等场合
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);
保存到文件默认为UNICODE格式
支持以下ANSI型输出:
//a系列dump为ansi编码输出
//bDisp为true按照友好格式显示,会输出\t换行等方便阅读
//bDisp为false按照紧凑模式显示,没有多余字符,方便网络传输等场合
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型输出主要用在节省网络带宽或者和其他系统交换数据的情况下。
支持以下类型判别函数:
//类型判别函数
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; }
支持以下一些直接取值函数:
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型子元素数据的函数:
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型子元素数据的函数:
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遍历函数:
//遍历函数,最常见写法:
//for(CJsonw::OBJIT *p=xxx.FirstObj(); p; p=p->next())...
OBJIT *firstobj()
//求array或object元素个数,string类型返回分配的字符个数(包括可能的),其他类型都返回
int size() const
另外支持一些增加array子元素函数:
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增加删除子对象函数:
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)); }
还有一些特殊函数:
//计算整个树的crc
DWORD calccrc();
//计算整个树的md5,要求md5不少于个字节
byte *calcmd5(byte *md5);
//计算hex表示的md5,不写尾部,要求md5hex不少于个字符
char *calcmd5hex(char *md5hex, const byte x='x');
//计算hex表示的md5,写尾部,要求md5hex不少于个字符
char *calcmd5hex0(char *md5hex, const byte x='x');
在json类上花了较多时间,主要是觉得这个类很有用,可以描述任意对象,易保存易传输易构造,对速度要求不苛刻的应用程序用json作为基本数据结构很合适,配合json里面的data自定义字段理论上支持描述任意对象,配合使用一些cache可扩大json类的使用范围,用它取代ini xml等配置简直是大材小用,用json类来做stringtable简直就是小菜一碟,而且还是hash级高效率,丝毫不比手工做一个hash_map<,>表差。
在实际应用中,去年有一个网络验证的项目就大量使用了这个类,配置、帮助都是json格式,应用中管理大量对象的内存数据库也是用了json类,编码后直接网上传输,server内部也是一个json对象直接管理了大量用户的信息,非常方便,可以说用json类使得这个程序少写了大量代码,也使得整个项目只用了1个月时间就做出来了,还部署成master – master- slave(N)模式稳定运行了将近1年时间。
在另一些网络应用中,俺将json格式数据作为变长包使用,前面俺写过一篇短文介绍了变长包最常见的几种格式,分别是:
1、 key\0value\0…
2、 json格式
3、 xml格式
使用json格式作为变长包现在很流行,这也是大量ajax所采用所依赖的技术,qq种菜,google搜索预列表都是采用json格式的。