-add options:_ex_args_nullable(0x01) _ex_args_exclude_decode(0x02) _ex_args_exclude_encode(0x04)
-fix compile error on g++ -add log when json decode error.
This commit is contained in:
parent
eddf45f4c6
commit
b826c74c71
79
README.md
79
README.md
|
@ -1,37 +1,35 @@
|
|||
# [简体中文](./README_zh.md) | English
|
||||
# 简体中文 | [English](./README_EN.md)
|
||||
|
||||
# cson
|
||||
Transformation between json string and struct.
|
||||
轻松完成C语言结构体和Json的转换。
|
||||
|
||||
The transformation between string to JSON objects (e.g. json_t in Jansson)
|
||||
is implemented by a third-party library (Jansson or cJSON. Refer to Dependence).
|
||||
What cson really implements is the transformation between JSON object and structure.
|
||||
其中Json字符串与Json对象(例如Jansson库中的json_t)之间的转换由第三方库实现(例如Jansson或者cJSON,请参考依赖库)。
|
||||
cson真正实现的是Json对象与结构体间的转换。
|
||||
|
||||
## Compilation
|
||||
### Compile static library
|
||||
## 编译
|
||||
### 编译静态库
|
||||
``` shell
|
||||
$ git clone https://github.com/sunchb/cson.git
|
||||
$ cd cson
|
||||
$ make
|
||||
```
|
||||
### Compile demo
|
||||
### 编译示例
|
||||
``` shell
|
||||
$ cd demo
|
||||
$ make
|
||||
$ ./test
|
||||
```
|
||||
## How to use
|
||||
1. Define the data structure for JSON.
|
||||
2. Define the property description table for data structure.
|
||||
3. Call cson api to decode or encode.
|
||||
## 如何使用cson
|
||||
1. 定义与Json协议对应的结构体。
|
||||
2. 定义结构体的属性描述表。
|
||||
3. 调用cson接口完成转换。
|
||||
|
||||
## Dependence
|
||||
## 依赖
|
||||
https://github.com/akheron/jansson.git
|
||||
https://github.com/DaveGamble/cJSON.git
|
||||
|
||||
## Demo
|
||||
Here is a JSON with various data types. eg. Interger, String, Real, Boolean, Object, and Array.
|
||||
We're going to decode and encode it by cson.
|
||||
## 示例
|
||||
下面具有各种数据类型的JSON。例如整数,字符串,实数,布尔值,对象和数组。我们将通过cson对其进行解码和编码。
|
||||
|
||||
``` json
|
||||
{
|
||||
|
@ -87,13 +85,13 @@ We're going to decode and encode it by cson.
|
|||
}
|
||||
```
|
||||
|
||||
### 1. Define the data structure for JSON.
|
||||
Even if you don't use cson, you usually need to do like this.
|
||||
### 1. 定义与Json协议对应的结构体。
|
||||
即使不使用cson,通常我们也会这么做。
|
||||
|
||||
#### Attention
|
||||
- String must be declared as char*.
|
||||
- Array must be declared as pointer.
|
||||
- Declare additional properties to hold the array size for every array property.
|
||||
#### 注意事项
|
||||
- 字符串必须定义为char*类型。
|
||||
- 数组必须定义为指针类型。
|
||||
- 如果结构体包含数组,需要为每一个数组定义一个额外的属性,用于保存数组大小。
|
||||
|
||||
``` c
|
||||
typedef struct {
|
||||
|
@ -127,8 +125,8 @@ typedef struct {
|
|||
} PlayList;
|
||||
```
|
||||
|
||||
### 2. Define the property description table for data structure.
|
||||
Use following definitions to help you describe the structure.
|
||||
### 2. 定义结构体的属性描述表。
|
||||
使用以下宏定义描述结构体属性。
|
||||
- _property_int(type, field)
|
||||
- _property_real(type, field)
|
||||
- _property_bool(type, field)
|
||||
|
@ -140,13 +138,32 @@ Use following definitions to help you describe the structure.
|
|||
- _property_array_real(type, field, arrayType, countfild)
|
||||
- _property_array_bool(type, field, arrayType, countfild)
|
||||
|
||||
Args notes:
|
||||
|
||||
参数说明:
|
||||
- type: type of data structure
|
||||
- field: property name
|
||||
- tbl: description table of the property type. use when object or object array
|
||||
- arrayType: type of the array (Used to calculate size when dynamically get array memory)
|
||||
- countfild: property to save array size
|
||||
|
||||
也可以使用带有扩展参数的宏定义,其中args可以是_ex_args_nullable, _ex_args_exclude_decode, _ex_args_exclude_encode的组合。
|
||||
- #define _ex_args_nullable (0x01) //不会因为该字段异常而停止后续字段解析, 该选项默认打开。
|
||||
- #define _ex_args_exclude_decode (0x02) //该字段不参与解析————例如指示数组元素个数的字段,Json中可以不包含它
|
||||
- #define _ex_args_exclude_encode (0x04) //该字段不参与格式化输出
|
||||
- #define _ex_args_all (_ex_args_nullable | _ex_args_exclude_decode | _ex_args_exclude_encode)
|
||||
|
||||
- _property_int_ex(type, field, args)
|
||||
- _property_real_ex(type, field, args)
|
||||
- _property_bool_ex(type, field, args)
|
||||
- _property_string_ex(type, field, args)
|
||||
- _property_obj_ex(type, field, tbl, args)
|
||||
- _property_array_ex(type, field, tbl, subType, count, args)
|
||||
- _property_array_object_ex(type, field, tbl, subType, count, args)
|
||||
- _property_array_int_ex(type, field, subType, count, args)
|
||||
- _property_array_string_ex(type, field, subType, count, args)
|
||||
- _property_array_real_ex(type, field, subType, count, args)
|
||||
- _property_array_bool_ex(type, field, subType, count, args)
|
||||
|
||||
``` c
|
||||
/* description for Lyric */
|
||||
reflect_item_t lyric_ref_tbl[] = {
|
||||
|
@ -164,7 +181,7 @@ reflect_item_t song_ref_tbl[] = {
|
|||
_property_int(SongInfo, duration),
|
||||
_property_bool(SongInfo, paid),
|
||||
_property_real(SongInfo, price),
|
||||
_property_int(SongInfo, lyricNum),
|
||||
_property_int_ex(SongInfo, lyricNum, _ex_args_all),
|
||||
_property_array(SongInfo, lyric, lyric_ref_tbl, Lyric, lyricNum), /* Lyric: type of array; lyricNum: property to save array size */
|
||||
_property_end()
|
||||
};
|
||||
|
@ -180,14 +197,14 @@ reflect_item_t ext_data_ref_tbl[] = {
|
|||
reflect_item_t play_list_ref_tbl[] = {
|
||||
_property_string(PlayList, name),
|
||||
_property_string(PlayList, creater),
|
||||
_property_int(PlayList, songNum),
|
||||
_property_int_ex(PlayList, songNum, _ex_args_all),
|
||||
_property_array(PlayList, songList, song_ref_tbl, SongInfo, songNum),
|
||||
_property_obj(PlayList, extData, ext_data_ref_tbl),
|
||||
_property_end()
|
||||
};
|
||||
```
|
||||
|
||||
### 3. Call cson api to decode or encode.
|
||||
### 3. 调用cson接口编解码Json。
|
||||
``` c
|
||||
PlayList playList;
|
||||
|
||||
|
@ -199,6 +216,6 @@ char* jstrOutput;
|
|||
csonStruct2JsonStr(&jstrOutput, &playList, play_list_ref_tbl);
|
||||
```
|
||||
|
||||
## Restrict
|
||||
- Multidimensional arrays are not supported.
|
||||
- Cjson is used by default. If you want to use jannson or other json lib, please modify $(JSON_LIB) in makefile.
|
||||
## 限制
|
||||
- 暂不支持多维数组。
|
||||
- 默认使用Cjson库。如果需要使用jannson,请修改Makefile中的$(JSON_LIB)变量。
|
||||
|
|
|
@ -1,35 +1,37 @@
|
|||
# 简体中文 | [English](./README.md)
|
||||
# 简体中文 | [English](./README_EN.md)
|
||||
|
||||
# cson
|
||||
轻松完成C语言结构体和Json的转换。
|
||||
Transformation between json string and struct.
|
||||
|
||||
其中Json字符串与Json对象(例如Jansson库中的json_t)之间的转换由第三方库实现(例如Jansson或者cJSON,请参考依赖库)。
|
||||
cson真正实现的是Json对象与结构体间的转换。
|
||||
The transformation between string to JSON objects (e.g. json_t in Jansson)
|
||||
is implemented by a third-party library (Jansson or cJSON. Refer to Dependence).
|
||||
What cson really implements is the transformation between JSON object and structure.
|
||||
|
||||
## 编译
|
||||
### 编译静态库
|
||||
## Compilation
|
||||
### Compile static library
|
||||
``` shell
|
||||
$ git clone https://github.com/sunchb/cson.git
|
||||
$ cd cson
|
||||
$ make
|
||||
```
|
||||
### 编译示例
|
||||
### Compile demo
|
||||
``` shell
|
||||
$ cd demo
|
||||
$ make
|
||||
$ ./test
|
||||
```
|
||||
## 如何使用cson
|
||||
1. 定义与Json协议对应的结构体。
|
||||
2. 定义结构体的属性描述表。
|
||||
3. 调用cson接口完成转换。
|
||||
## How to use
|
||||
1. Define the data structure for JSON.
|
||||
2. Define the property description table for data structure.
|
||||
3. Call cson api to decode or encode.
|
||||
|
||||
## 依赖
|
||||
## Dependence
|
||||
https://github.com/akheron/jansson.git
|
||||
https://github.com/DaveGamble/cJSON.git
|
||||
|
||||
## 示例
|
||||
下面具有各种数据类型的JSON。例如整数,字符串,实数,布尔值,对象和数组。我们将通过cson对其进行解码和编码。
|
||||
## Demo
|
||||
Here is a JSON with various data types. eg. Interger, String, Real, Boolean, Object, and Array.
|
||||
We're going to decode and encode it by cson.
|
||||
|
||||
``` json
|
||||
{
|
||||
|
@ -85,13 +87,13 @@ https://github.com/DaveGamble/cJSON.git
|
|||
}
|
||||
```
|
||||
|
||||
### 1. 定义与Json协议对应的结构体。
|
||||
即使不使用cson,通常我们也会这么做。
|
||||
### 1. Define the data structure for JSON.
|
||||
Even if you don't use cson, you usually need to do like this.
|
||||
|
||||
#### 注意事项
|
||||
- 字符串必须定义为char*类型。
|
||||
- 数组必须定义为指针类型。
|
||||
- 如果结构体包含数组,需要为每一个数组定义一个额外的属性,用于保存数组大小。
|
||||
#### Attention
|
||||
- String must be declared as char*.
|
||||
- Array must be declared as pointer.
|
||||
- Declare additional properties to hold the array size for every array property.
|
||||
|
||||
``` c
|
||||
typedef struct {
|
||||
|
@ -125,8 +127,8 @@ typedef struct {
|
|||
} PlayList;
|
||||
```
|
||||
|
||||
### 2. 定义结构体的属性描述表。
|
||||
使用以下宏定义描述结构体属性。
|
||||
### 2. Define the property description table for data structure.
|
||||
Use following definitions to help you describe the structure.
|
||||
- _property_int(type, field)
|
||||
- _property_real(type, field)
|
||||
- _property_bool(type, field)
|
||||
|
@ -138,13 +140,31 @@ typedef struct {
|
|||
- _property_array_real(type, field, arrayType, countfild)
|
||||
- _property_array_bool(type, field, arrayType, countfild)
|
||||
|
||||
参数说明:
|
||||
Args notes:
|
||||
- type: type of data structure
|
||||
- field: property name
|
||||
- tbl: description table of the property type. use when object or object array
|
||||
- arrayType: type of the array (Used to calculate size when dynamically get array memory)
|
||||
- countfild: property to save array size
|
||||
|
||||
You can also use macro definitions with extended parameters, the range of args is _ex_args_nullable, _ex_args_exclude_decode, _ex_args_exclude_encode and thire combinations.
|
||||
- #define _ex_args_nullable (0x01) //continue parse or encode when the field exception occurred. Default is "ON".
|
||||
- #define _ex_args_exclude_decode (0x02) //do not parse the field.
|
||||
- #define _ex_args_exclude_encode (0x04) //do not encode the field.
|
||||
- #define _ex_args_all (_ex_args_nullable | _ex_args_exclude_decode | _ex_args_exclude_encode)
|
||||
|
||||
- _property_int_ex(type, field, args)
|
||||
- _property_real_ex(type, field, args)
|
||||
- _property_bool_ex(type, field, args)
|
||||
- _property_string_ex(type, field, args)
|
||||
- _property_obj_ex(type, field, tbl, args)
|
||||
- _property_array_ex(type, field, tbl, subType, count, args)
|
||||
- _property_array_object_ex(type, field, tbl, subType, count, args)
|
||||
- _property_array_int_ex(type, field, subType, count, args)
|
||||
- _property_array_string_ex(type, field, subType, count, args)
|
||||
- _property_array_real_ex(type, field, subType, count, args)
|
||||
- _property_array_bool_ex(type, field, subType, count, args)
|
||||
|
||||
``` c
|
||||
/* description for Lyric */
|
||||
reflect_item_t lyric_ref_tbl[] = {
|
||||
|
@ -185,7 +205,7 @@ reflect_item_t play_list_ref_tbl[] = {
|
|||
};
|
||||
```
|
||||
|
||||
### 3. 调用cson接口编解码Json。
|
||||
### 3. Call cson api to decode or encode.
|
||||
``` c
|
||||
PlayList playList;
|
||||
|
||||
|
@ -197,6 +217,6 @@ char* jstrOutput;
|
|||
csonStruct2JsonStr(&jstrOutput, &playList, play_list_ref_tbl);
|
||||
```
|
||||
|
||||
## 限制
|
||||
- 暂不支持多维数组。
|
||||
- 默认使用Cjson库。如果需要使用jannson,请修改Makefile中的$(JSON_LIB)变量。
|
||||
## Restrict
|
||||
- Multidimensional arrays are not supported.
|
||||
- Cjson is used by default. If you want to use jannson or other json lib, please modify $(JSON_LIB) in makefile.
|
|
@ -5,6 +5,7 @@
|
|||
#include "cJSON.h"
|
||||
#include "cson.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
|
||||
cson_t cjson_impl_object_get(const cson_t object, const char* key){
|
||||
return cJSON_GetObjectItem((cJSON*)object, key);
|
||||
|
@ -34,7 +35,12 @@ cson_type cjson_impl_typeof(cson_t object){
|
|||
}
|
||||
|
||||
cson_t cjson_impl_loadb(const char *buffer, size_t buflen){
|
||||
return cJSON_Parse(buffer);
|
||||
cson_t ret = NULL;
|
||||
ret = cJSON_Parse(buffer);
|
||||
if(!ret){
|
||||
printf("parse stop with:%s\n", cJSON_GetErrorPtr());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cjson_impl_decref(cson_t object){
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
#include "cson.h"
|
||||
#include "jansson.h"
|
||||
#include "stdio.h"
|
||||
|
||||
cson_t jansson_impl_object_get(const cson_t object, const char* key){
|
||||
return json_object_get((json_t*)object, key);
|
||||
|
@ -14,8 +15,20 @@ cson_type jansson_impl_typeof(cson_t object){
|
|||
}
|
||||
|
||||
cson_t jansson_impl_loadb(const char *buffer, size_t buflen){
|
||||
cson_t ret = NULL;
|
||||
json_error_t err;
|
||||
return json_loadb(buffer, buflen, JSON_DECODE_ANY, &err);
|
||||
|
||||
ret = json_loadb(buffer, buflen, JSON_DECODE_ANY, &err);
|
||||
|
||||
if(!ret){
|
||||
printf("line:%d,column:%d,pos:%d,source:%s,text:%s\n",
|
||||
err.line,
|
||||
err.column,
|
||||
err.position,
|
||||
err.source,
|
||||
err.text);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void jansson_impl_decref(cson_t object){
|
||||
|
|
|
@ -4,9 +4,9 @@ extern void test2();
|
|||
#include "cson.h"
|
||||
#include "stdio.h"
|
||||
|
||||
void main()
|
||||
int main()
|
||||
{
|
||||
test1();
|
||||
test2();
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
|
83
demo/test.c
83
demo/test.c
|
@ -3,6 +3,12 @@
|
|||
#include "string.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
#include "assert.h"
|
||||
#include "math.h"
|
||||
|
||||
#define CHECK_STRING(a, b) assert(strcmp(a, b) == 0)
|
||||
#define CHECK_NUMBER(a, b) assert(a == b)
|
||||
#define CHECK_REAL(a, b) assert(fabs(a-b) <= 1e-6)
|
||||
/**
|
||||
* 该示例会使用cson解析如下所示播放列表。
|
||||
*
|
||||
|
@ -142,11 +148,11 @@ reflect_item_t song_ref_tbl[] = {
|
|||
_property_int(SongInfo, duration),
|
||||
_property_bool(SongInfo, paid),
|
||||
_property_real(SongInfo, price),
|
||||
_property_int(SongInfo, lyricNum),
|
||||
_property_int_ex(SongInfo, lyricNum, _ex_args_all),
|
||||
_property_array_object(SongInfo, lyric, lyric_ref_tbl, Lyric, lyricNum),
|
||||
_property_int(SongInfo, keyNum),
|
||||
_property_int_ex(SongInfo, keyNum, _ex_args_all),
|
||||
_property_array_int(SongInfo, key, int, keyNum),
|
||||
_property_int(SongInfo, strNum),
|
||||
_property_int_ex(SongInfo, strNum, _ex_args_all),
|
||||
_property_array_string(SongInfo, strList, char*, strNum),
|
||||
_property_end()
|
||||
};
|
||||
|
@ -160,7 +166,7 @@ reflect_item_t ext_data_ref_tbl[] = {
|
|||
reflect_item_t play_list_ref_tbl[] = {
|
||||
_property_string(PlayList, name),
|
||||
_property_string(PlayList, creater),
|
||||
_property_int(PlayList, songNum),
|
||||
_property_int_ex(PlayList, songNum, _ex_args_all),
|
||||
_property_array_object(PlayList, songList, song_ref_tbl, SongInfo, songNum),
|
||||
_property_obj(PlayList, extData, ext_data_ref_tbl),
|
||||
_property_end()
|
||||
|
@ -171,6 +177,7 @@ static void freePlayList(PlayList* list);
|
|||
|
||||
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}}";
|
||||
|
||||
static void checkResult(PlayList* playList, char* jstrOutput);
|
||||
/*
|
||||
Step3:调用csonJsonStr2Struct/csonStruct2JsonStr实现反序列化和序列化
|
||||
*/
|
||||
|
@ -180,16 +187,78 @@ void test1()
|
|||
printf("\t\tRunning %s\n", __FUNCTION__);
|
||||
printf("=========================================\n");
|
||||
PlayList playList;
|
||||
memset(&playList, 0, sizeof(playList));
|
||||
|
||||
/* string to struct */
|
||||
int ret = csonJsonStr2Struct(jStr, &playList, play_list_ref_tbl);
|
||||
CHECK_NUMBER(ret, 0);
|
||||
printf("decode ret=%d\n", ret);
|
||||
/* test print */
|
||||
printf("ret=%d\n", ret);
|
||||
csonPrintProperty(&playList, play_list_ref_tbl);
|
||||
//csonPrintProperty(&playList, play_list_ref_tbl);
|
||||
|
||||
char* jstrOutput;
|
||||
ret = csonStruct2JsonStr(&jstrOutput, &playList, play_list_ref_tbl);
|
||||
printf("ret=%d\nJson:%s\n", ret, jstrOutput);
|
||||
CHECK_NUMBER(ret, 0);
|
||||
printf("encode ret=%d\nJson:%s\n", ret, jstrOutput);
|
||||
|
||||
/*assert check*/
|
||||
checkResult(&playList, jstrOutput);
|
||||
|
||||
free(jstrOutput);
|
||||
csonFreePointer(&playList, play_list_ref_tbl);
|
||||
|
||||
printf("Successed %s.\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
|
||||
void checkResult(PlayList* playList, char* jstrOutput){
|
||||
const char* encodeTest = "{\"name\":\"jay zhou\",\"creater\":\"dahuaxia\",\"songList\":[{\"songName\":\"qilixiang\",\"signerName\":\"jay zhou\",\"albumName\":\"qilixiang\",\"url\":\"www.kugou.com\",\"duration\":0,\"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,\"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}}";
|
||||
|
||||
/* assert test */
|
||||
CHECK_STRING(playList->name, "jay zhou");
|
||||
CHECK_STRING(playList->creater, "dahuaxia");
|
||||
CHECK_NUMBER(playList->songNum, 2);
|
||||
CHECK_STRING(playList->songList[0].songName, "qilixiang");
|
||||
CHECK_STRING(playList->songList[0].signerName, "jay zhou");
|
||||
CHECK_STRING(playList->songList[0].albumName, "qilixiang");
|
||||
CHECK_STRING(playList->songList[0].url, "www.kugou.com");
|
||||
CHECK_NUMBER(playList->songList[0].duration, 0);
|
||||
CHECK_NUMBER(playList->songList[0].paid, 0);
|
||||
CHECK_REAL(playList->songList[0].price, 6.66);
|
||||
CHECK_NUMBER(playList->songList[0].lyricNum, 2);
|
||||
CHECK_NUMBER(playList->songList[0].lyric[0].time, 1);
|
||||
CHECK_STRING(playList->songList[0].lyric[0].text, "Sparrow outside the window");
|
||||
CHECK_NUMBER(playList->songList[0].lyric[1].time, 10);
|
||||
CHECK_STRING(playList->songList[0].lyric[1].text, "Multi mouth on the pole");
|
||||
CHECK_NUMBER(playList->songList[0].keyNum, 3);
|
||||
CHECK_NUMBER(playList->songList[0].key[0], 1111);
|
||||
CHECK_NUMBER(playList->songList[0].key[1], 2222);
|
||||
CHECK_NUMBER(playList->songList[0].key[2], 3333);
|
||||
CHECK_NUMBER(playList->songList[0].strNum, 0);
|
||||
|
||||
CHECK_STRING(playList->songList[1].songName, "dongfengpo");
|
||||
CHECK_STRING(playList->songList[1].signerName, "jay zhou");
|
||||
CHECK_STRING(playList->songList[1].albumName, "dongfengpo");
|
||||
CHECK_STRING(playList->songList[1].url, "music.qq.com");
|
||||
CHECK_NUMBER(playList->songList[1].duration, 180);
|
||||
CHECK_NUMBER(playList->songList[1].paid, 1);
|
||||
CHECK_REAL(playList->songList[1].price, 0.88);
|
||||
CHECK_NUMBER(playList->songList[1].lyricNum, 2);
|
||||
CHECK_NUMBER(playList->songList[1].lyric[0].time, 10);
|
||||
CHECK_STRING(playList->songList[1].lyric[0].text, "A sad parting, standing alone in the window");
|
||||
CHECK_NUMBER(playList->songList[1].lyric[1].time, 20);
|
||||
CHECK_STRING(playList->songList[1].lyric[1].text, "I'm behind the door pretending you're not gone");
|
||||
CHECK_NUMBER(playList->songList[1].keyNum, 3);
|
||||
CHECK_NUMBER(playList->songList[1].key[0], 1234);
|
||||
CHECK_NUMBER(playList->songList[1].key[1], 5678);
|
||||
CHECK_NUMBER(playList->songList[1].key[2], 9876);
|
||||
CHECK_NUMBER(playList->songList[1].strNum, 3);
|
||||
CHECK_STRING(playList->songList[1].strList[0], "abcd");
|
||||
CHECK_STRING(playList->songList[1].strList[1], "efgh");
|
||||
CHECK_STRING(playList->songList[1].strList[2], "ijkl");
|
||||
CHECK_NUMBER(playList->extData.a, 999);
|
||||
CHECK_REAL(playList->extData.b, 1);
|
||||
|
||||
//It is difficult to predict the output due to the accuracy problem.
|
||||
//CHECK_STRING(jstrOutput, encodeTest);
|
||||
}
|
170
demo/test2.c
170
demo/test2.c
File diff suppressed because one or more lines are too long
43
inc/cson.h
43
inc/cson.h
|
@ -90,14 +90,14 @@ typedef struct {
|
|||
* @TODO: Try to simplify the struct
|
||||
*/
|
||||
typedef struct reflect_item_t {
|
||||
char* field; /**< field */
|
||||
const char* field; /**< field */
|
||||
size_t offset; /**< offset of property */
|
||||
size_t size; /**< size of property */
|
||||
cson_type type; /**< corresponding json type */
|
||||
const struct reflect_item_t* reflect_tbl; /**< must be specified when type is object or array */
|
||||
size_t arrayItemSize; /**< size of per array item. must be specified when type is array */
|
||||
char* arrayCountField; /**< field saving array size */
|
||||
int nullable; /**< paser return failure when the field is not found and nullable equals to 0 */
|
||||
const char* arrayCountField; /**< field saving array size */
|
||||
int exArgs; /**< paser return failure when the field is not found and nullable equals to 0 */
|
||||
} reflect_item_t;
|
||||
|
||||
extern const reflect_item_t integerReflectTbl[];
|
||||
|
@ -105,7 +105,12 @@ extern const reflect_item_t stringReflectTbl[];
|
|||
extern const reflect_item_t boolReflectTbl[];
|
||||
extern const reflect_item_t realReflectTbl[];
|
||||
|
||||
#define _offset(type, field) (&(((type*)0)->field))
|
||||
#define _ex_args_nullable (0x01)
|
||||
#define _ex_args_exclude_decode (0x02)
|
||||
#define _ex_args_exclude_encode (0x04)
|
||||
#define _ex_args_all (_ex_args_nullable | _ex_args_exclude_decode | _ex_args_exclude_encode)
|
||||
|
||||
#define _offset(type, field) (size_t)(&(((type*)0)->field))
|
||||
#define _size(type, field) (sizeof(((type*)0)->field))
|
||||
#define _property(type, field, jtype, tbl, nullable) {#field, _offset(type, field), _size(type, field), jtype, tbl, 0, NULL, nullable}
|
||||
#define _property_end() {NULL, 0, 0, CSON_NULL, NULL, 0, NULL, 1}
|
||||
|
@ -117,7 +122,7 @@ extern const reflect_item_t realReflectTbl[];
|
|||
* @param field: field name of properties
|
||||
*
|
||||
*/
|
||||
#define _property_int(type, field) _property(type, field, CSON_INTEGER, integerReflectTbl, 1)
|
||||
#define _property_int(type, field) _property(type, field, CSON_INTEGER, integerReflectTbl, _ex_args_nullable)
|
||||
|
||||
/**
|
||||
* @brief Declaring real properties.
|
||||
|
@ -126,7 +131,7 @@ extern const reflect_item_t realReflectTbl[];
|
|||
* @param field: field name of properties
|
||||
*
|
||||
*/
|
||||
#define _property_real(type, field) _property(type, field, CSON_REAL, realReflectTbl, 1)
|
||||
#define _property_real(type, field) _property(type, field, CSON_REAL, realReflectTbl, _ex_args_nullable)
|
||||
|
||||
/**
|
||||
* @brief Declaring bool properties.
|
||||
|
@ -135,7 +140,7 @@ extern const reflect_item_t realReflectTbl[];
|
|||
* @param field: field name of properties
|
||||
*
|
||||
*/
|
||||
#define _property_bool(type, field) _property(type, field, CSON_TRUE, boolReflectTbl, 1)
|
||||
#define _property_bool(type, field) _property(type, field, CSON_TRUE, boolReflectTbl, _ex_args_nullable)
|
||||
|
||||
/**
|
||||
* @brief Declaring string properties.
|
||||
|
@ -144,7 +149,7 @@ extern const reflect_item_t realReflectTbl[];
|
|||
* @param field: field name of properties
|
||||
*
|
||||
*/
|
||||
#define _property_string(type, field) _property(type, field, CSON_STRING, stringReflectTbl, 1)
|
||||
#define _property_string(type, field) _property(type, field, CSON_STRING, stringReflectTbl, _ex_args_nullable)
|
||||
|
||||
/**
|
||||
* @brief Declaring struct properties.
|
||||
|
@ -154,7 +159,7 @@ extern const reflect_item_t realReflectTbl[];
|
|||
* @param tbl: property description table of sub-struct
|
||||
*
|
||||
*/
|
||||
#define _property_obj(type, field, tbl) _property(type, field, CSON_OBJECT, tbl, 1)
|
||||
#define _property_obj(type, field, tbl) _property(type, field, CSON_OBJECT, tbl, _ex_args_nullable)
|
||||
|
||||
/**
|
||||
* @brief Declaring array properties.
|
||||
|
@ -166,7 +171,7 @@ extern const reflect_item_t realReflectTbl[];
|
|||
* @param count: property to save the array size
|
||||
*
|
||||
*/
|
||||
#define _property_array(type, field, tbl, subType, count) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), #count, 1}
|
||||
#define _property_array(type, field, tbl, subType, count) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), #count, _ex_args_nullable}
|
||||
#define _property_array_object(type, field, tbl, subType, count) _property_array(type, field, tbl, subType, count)
|
||||
#define _property_array_int(type, field, subType, count) _property_array(type, field, integerReflectTbl, subType, count)
|
||||
#define _property_array_string(type, field, subType, count) _property_array(type, field, stringReflectTbl, subType, count)
|
||||
|
@ -190,6 +195,24 @@ extern const reflect_item_t realReflectTbl[];
|
|||
#define _property_array_real_nonull(type, field, subType, count) _property_array_nonull(type, field, realReflectTbl, subType, count)
|
||||
#define _property_array_bool_nonull(type, field, subType, count) _property_array_nonull(type, field, boolReflectTbl, subType, count)
|
||||
|
||||
/**
|
||||
* @brief nonull definitions. parser will stop and return error code when field not found which declared whit it.
|
||||
*
|
||||
* @param refer to comment of nullable definition
|
||||
* @param args opptional with _ex_args_nullable(0x01) _ex_args_exclude_decode(0x02) _ex_args_exclude_encode(0x04)
|
||||
*/
|
||||
#define _property_int_ex(type, field, args) _property(type, field, CSON_INTEGER, NULL, args)
|
||||
#define _property_real_ex(type, field, args) _property(type, field, CSON_REAL, NULL, args)
|
||||
#define _property_bool_ex(type, field, args) _property(type, field, CSON_TRUE, NULL, args)
|
||||
#define _property_string_ex(type, field, args) _property(type, field, CSON_STRING, NULL, args)
|
||||
#define _property_obj_ex(type, field, tbl, args) _property(type, field, CSON_OBJECT, tbl, args)
|
||||
#define _property_array_ex(type, field, tbl, subType, count, args) {#field, _offset(type, field), _size(type, field), CSON_ARRAY, tbl, sizeof(subType), #count, args}
|
||||
#define _property_array_object_ex(type, field, tbl, subType, count, args) _property_array_ex(type, field, tbl, subType, count)
|
||||
#define _property_array_int_ex(type, field, subType, count, args) _property_array_ex(type, field, integerReflectTbl, subType, count)
|
||||
#define _property_array_string_ex(type, field, subType, count, args) _property_array_ex(type, field, stringReflectTbl, subType, count)
|
||||
#define _property_array_real_ex(type, field, subType, count, args) _property_array_ex(type, field, realReflectTbl, subType, count)
|
||||
#define _property_array_bool_ex(type, field, subType, count, args) _property_array_ex(type, field, boolReflectTbl, subType, count)
|
||||
|
||||
/**
|
||||
* @brief function type of csonLoopProperty.
|
||||
*
|
||||
|
|
28
src/cson.c
28
src/cson.c
|
@ -175,6 +175,11 @@ int csonStruct2JsonObj(cson_t obj, void* input, const reflect_item_t* tbl)
|
|||
while (1) {
|
||||
if (tbl[i].field == NULL) break;
|
||||
|
||||
if(tbl[i].exArgs & _ex_args_exclude_encode){
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
cson_t joTmp = NULL;
|
||||
int jsonType = tbl[i].type;
|
||||
|
||||
|
@ -184,7 +189,7 @@ int csonStruct2JsonObj(cson_t obj, void* input, const reflect_item_t* tbl)
|
|||
|
||||
if (ret != ERR_NONE ) {
|
||||
printf("!!!!pack error on field:%s, cod=%d!!!!\n", tbl[i].field, ret);
|
||||
if (!tbl[i].nullable) return ret;
|
||||
if (!(tbl[i].exArgs & _ex_args_nullable)) return ret;
|
||||
} else {
|
||||
cson_object_set_new(obj, tbl[i].field, joTmp);
|
||||
}
|
||||
|
@ -350,6 +355,10 @@ int csonJsonObj2Struct(cson_t jo, void* output, const reflect_item_t* tbl)
|
|||
int ret = ERR_NONE;
|
||||
if (tbl[i].field == NULL) break;
|
||||
|
||||
if(tbl[i].exArgs & _ex_args_exclude_decode){
|
||||
continue;
|
||||
}
|
||||
|
||||
cson_t jo_tmp = cson_object_get(jo, tbl[i].field);
|
||||
|
||||
if (jo_tmp == NULL) {
|
||||
|
@ -372,7 +381,7 @@ int csonJsonObj2Struct(cson_t jo, void* output, const reflect_item_t* tbl)
|
|||
if (ret != ERR_NONE ) {
|
||||
printf("!!!!parse error on field:%s, cod=%d!!!!\n", tbl[i].field, ret);
|
||||
jsonObjDefaultTbl[tbl[i].type](NULL, output, tbl, i);
|
||||
if (!tbl[i].nullable) return ret;
|
||||
if (!(tbl[i].exArgs & _ex_args_nullable)) return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -383,7 +392,7 @@ int parseJsonString(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int
|
|||
{
|
||||
const char* tempstr = cson_string_value(jo_tmp);
|
||||
if (NULL != tempstr) {
|
||||
char* pDst = malloc(strlen(tempstr) + 1);
|
||||
char* pDst = (char*)malloc(strlen(tempstr) + 1);
|
||||
if (pDst == NULL) {
|
||||
return ERR_MEMORY;
|
||||
}
|
||||
|
@ -435,6 +444,8 @@ int parseJsonArray(cson_t jo_tmp, void* output, const reflect_item_t* tbl, int i
|
|||
char* pMem = (char*)malloc(arraySize * tbl[index].arrayItemSize);
|
||||
if (pMem == NULL) return ERR_MEMORY;
|
||||
|
||||
memset(pMem, 0, arraySize * tbl[index].arrayItemSize);
|
||||
|
||||
long long successCount = 0;
|
||||
for (size_t j = 0; j < arraySize; j++) {
|
||||
cson_t item = cson_array_get(jo_tmp, j);
|
||||
|
@ -507,7 +518,13 @@ int parseJsonObjectDefault(cson_t jo_tmp, void* output, const reflect_item_t* tb
|
|||
{
|
||||
int i = 0;
|
||||
while (1) {
|
||||
if (tbl[index].reflect_tbl[i].field == NULL) break;
|
||||
if (tbl[i].reflect_tbl[i].field == NULL) break;
|
||||
|
||||
if(tbl[i].exArgs & _ex_args_exclude_decode){
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
jsonObjDefaultTbl[tbl[index].reflect_tbl[i].type](NULL, output, tbl[index].reflect_tbl, i);
|
||||
i++;
|
||||
};
|
||||
|
@ -745,8 +762,9 @@ static void* printPropertySub(void* pData, const reflect_item_t* tbl)
|
|||
static void* freePointerSub(void* pData, const reflect_item_t* tbl)
|
||||
{
|
||||
if (tbl->type == CSON_ARRAY || tbl->type == CSON_STRING) {
|
||||
printf("free field %s.\n", tbl->field);
|
||||
//printf("free field %s.\n", tbl->field);
|
||||
free(*(void**)pData);
|
||||
*(void**)pData = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue