2019-12-24 23:13:45 -08:00
# include "cson.h"
# include "stdio.h"
# include "string.h"
# include "stdlib.h"
/**
* 该 示 例 会 使 用 cson解析如下所示播放列表 。
*
{
" name " : " jay zhou " ,
" creater " : " dahuaxia " ,
" songNum " : 2 ,
" songList " : [
{
" songName " : " qilixiang " ,
" signerName " : " jay zhou " ,
" albumName " : " qilixiang " ,
" url " : " www.kugou.com " ,
" duration " : 200 ,
" paid " : false ,
" price " : 6.6600000000000001 ,
" lyricNum " : 2 ,
" lyric " : [
{
" time " : 1 ,
" text " : " Sparrow outside the window "
} ,
{
" time " : 10 ,
" text " : " Multi mouth on the pole "
}
] ,
" key " : [
1234 ,
5678 ,
9876
]
} ,
{
" songName " : " dongfengpo " ,
" signerName " : " jay zhou " ,
" albumName " : " dongfengpo " ,
" url " : " music.qq.com " ,
" duration " : 180 ,
" paid " : true ,
" price " : 0.88 ,
" lyricNum " : 2 ,
" lyric " : [
{
" time " : 10 ,
" text " : " A sad parting, standing alone in the window "
} ,
{
" time " : 20 ,
" text " : " I'm behind the door pretending you're not gone "
}
] ,
" key " : [
1111 ,
2222 ,
3333
]
}
] ,
" extData " : {
" a " : 999 ,
" b " : 1.05
}
}
*/
/**
* 1 ) 首 先 我 们 需 要 定 义 与 上 面 json相对应的数据结构 。 于 是 有 了 @ PlayList 、 @ ExtData 、 @ SongInfo 、 @ Lyric 。
* 即 使 不 实 用 cson , 想 要 解 析 json , 通 常 你 也 需 要 这 么 做 。
*
* 注 意 : 结 构 体 属 性 名 需 与 json中字段名一致 ;
* 注 意 : 当 某 个 字 段 在 json中被定义为数组时 , 那 么 该 字 段 在 结 构 体 中 要 被 声 名 为 指 针 , 并 且 增 加 数 组 size的字段 。
*
* 2 ) 为 了 C语言能够像java中通过反射来操作结构体中的属性 , 我 们 需 要 先 为 每 个 结 构 体 定 义 一 个 用 于 查 找 结 构 体 属 性 的 “ 反 射 表 ” ,
* 即 play_list_ref_tbl , ext_data_ref_tbl , song_ref_tbl , lyric_ref_tbl 。
* 有 了 这 个 反 射 表 , 我 们 可 以 迭 代 访 问 数 组 元 素 。 不 仅 可 以 帮 助 我 们 完 成 json解析 , 当 我 们 想 要 输 出 对 象 各 属 性 值 、 或 是 释 放
* 指 针 指 向 的 堆 内 存 时 也 很 有 用 。
*
* TODO : 目 前 反 射 表 的 结 构 有 些 复 杂 , 虽 然 提 供 了 宏 定 义 让 它 用 来 稍 稍 方 便 一 些 。 需 要 对 该 结 构 做 出 优 化 。
*
* 3 ) 正 确 的 完 成 上 面 两 步 , 解 析 工 作 其 实 基 本 上 就 要 完 成 了 。 只 要 再 调 用 csonJsonStr2Struct , 所 有 的 属 性 就 都 会 正 确 的 赋 值 到 结 构 体 。
*
*/
/*
Step1 : 定 义 与 json相对应的数据结构
*/
typedef struct {
int time ;
char * text ;
} Lyric ;
typedef struct {
char * songName ;
char * signerName ;
char * albumName ;
char * url ;
int duration ;
int paid ;
double price ;
size_t lyricNum ;
Lyric * lyric ;
size_t keyNum ;
int * key ;
size_t strNum ;
char * * strList ;
} SongInfo ;
typedef struct {
int a ;
double b ;
} ExtData ;
typedef struct {
char * name ;
char * creater ;
size_t songNum ;
SongInfo * songList ;
ExtData extData ;
} PlayList ;
/*
Step2 : 定 义 数 据 结 构 的 反 射 表
*/
reflect_item_t lyric_ref_tbl [ ] = {
_property_int ( Lyric , time ) ,
_property_string ( Lyric , text ) ,
_property_end ( )
} ;
reflect_item_t song_ref_tbl [ ] = {
_property_string ( SongInfo , songName ) ,
_property_string ( SongInfo , signerName ) ,
_property_string ( SongInfo , albumName ) ,
_property_string ( SongInfo , url ) ,
_property_int ( SongInfo , duration ) ,
_property_bool ( SongInfo , paid ) ,
_property_real ( SongInfo , price ) ,
_property_int ( SongInfo , lyricNum ) ,
_property_array_object ( SongInfo , lyric , lyric_ref_tbl , Lyric , lyricNum ) ,
_property_int ( SongInfo , keyNum ) ,
_property_array_int ( SongInfo , key , int , keyNum ) ,
_property_int ( SongInfo , strNum ) ,
_property_array_string ( SongInfo , strList , char * , strNum ) ,
_property_end ( )
} ;
reflect_item_t ext_data_ref_tbl [ ] = {
_property_int ( ExtData , a ) ,
_property_real ( ExtData , b ) ,
_property_end ( )
} ;
reflect_item_t play_list_ref_tbl [ ] = {
_property_string ( PlayList , name ) ,
_property_string ( PlayList , creater ) ,
_property_int ( PlayList , songNum ) ,
_property_array_object ( PlayList , songList , song_ref_tbl , SongInfo , songNum ) ,
_property_obj ( PlayList , extData , ext_data_ref_tbl ) ,
_property_end ( )
} ;
2020-02-05 12:16:15 +08:00
static void printPlayList ( PlayList * list ) ;
static void freePlayList ( PlayList * list ) ;
2019-12-24 23:13:45 -08:00
const static char * jStr = " { \" name \" : \" jay zhou \" , \" creater \" : \" dahuaxia \" , \" songList \" :[{ \" songName \" : \" qilixiang \" , \" signerName \" : \" jay zhou \" , \" albumName \" : \" qilixiang \" , \" url \" : \" www.kugou.com \" , \" duration \" :20093999939292928292234.1, \" paid \" :false, \" price \" :6.66, \" lyric \" :[{ \" time \" :1, \" text \" : \" Sparrow outside the window \" },{ \" time \" :10, \" text \" : \" Multi mouth on the pole \" }], \" key \" :[1111,2222,3333]},{ \" songName \" : \" dongfengpo \" , \" signerName \" : \" jay zhou \" , \" albumName \" : \" dongfengpo \" , \" url \" : \" music.qq.com \" , \" duration \" :180.9, \" paid \" :true, \" price \" :0.88, \" lyric \" :[{ \" time \" :10, \" text \" : \" A sad parting, standing alone in the window \" },{ \" time \" :20, \" text \" : \" I'm behind the door pretending you're not gone \" }], \" key \" :[1234,5678,9876], \" strList \" :[ \" abcd \" , \" efgh \" , \" ijkl \" ]}], \" extData \" :{ \" a \" :999, \" b \" :1}} " ;
/*
Step3 : 调 用 csonJsonStr2Struct / csonStruct2JsonStr实现反序列化和序列化
*/
void test1 ( )
{
printf ( " ========================================= \n " ) ;
printf ( " \t \t Running %s \n " , __FUNCTION__ ) ;
printf ( " ========================================= \n " ) ;
PlayList playList ;
/* string to struct */
int ret = csonJsonStr2Struct ( jStr , & playList , play_list_ref_tbl ) ;
/* test print */
printf ( " ret=%d \n " , ret ) ;
printPlayList ( & playList ) ;
char * jstrOutput ;
ret = csonStruct2JsonStr ( & jstrOutput , & playList , play_list_ref_tbl ) ;
printf ( " ret=%d \n Json:%s \n " , ret , jstrOutput ) ;
free ( jstrOutput ) ;
freePlayList ( & playList ) ;
}
2020-02-05 12:16:15 +08:00
static void * printProperty ( void * pData , const reflect_item_t * tbl )
2019-12-24 23:13:45 -08:00
{
if ( tbl - > type = = CSON_ARRAY | | tbl - > type = = CSON_OBJECT ) return NULL ;
if ( tbl - > type = = CSON_INTEGER | | tbl - > type = = CSON_TRUE | | tbl - > type = = CSON_FALSE ) printf ( " %s:%d \n " , tbl - > field , * ( int * ) pData ) ;
if ( tbl - > type = = CSON_REAL ) printf ( " %s:%f \n " , tbl - > field , * ( double * ) pData ) ;
if ( tbl - > type = = CSON_STRING ) printf ( " %s:%s \n " , tbl - > field , * ( ( char * * ) pData ) ) ;
return NULL ;
}
2020-02-05 12:16:15 +08:00
static void * freePointer ( void * pData , const reflect_item_t * tbl )
2019-12-24 23:13:45 -08:00
{
if ( tbl - > type = = CSON_ARRAY | | tbl - > type = = CSON_STRING ) {
printf ( " free field %s. \n " , tbl - > field ) ;
free ( * ( void * * ) pData ) ;
}
return NULL ;
}
2020-02-05 12:16:15 +08:00
static void printPlayList ( PlayList * list )
2019-12-24 23:13:45 -08:00
{
/* 调用loopProperty迭代结构体中的属性,完成迭代输出属性值 */
csonLoopProperty ( list , play_list_ref_tbl , printProperty ) ;
}
2020-02-05 12:16:15 +08:00
static void freePlayList ( PlayList * list )
2019-12-24 23:13:45 -08:00
{
/* 调用loopProperty迭代结构体中的属性,释放字符串和数组申请的内存空间 */
csonLoopProperty ( list , play_list_ref_tbl , freePointer ) ;
}